mithril-materialized 3.4.5 → 3.5.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/advanced.css +141 -2
- package/dist/components.css +141 -2
- package/dist/index.css +143 -2
- package/dist/index.esm.js +217 -17
- package/dist/index.js +217 -17
- package/dist/index.min.css +1 -1
- package/dist/index.umd.js +217 -17
- package/dist/material-icon.d.ts +6 -0
- package/dist/sidenav.d.ts +29 -1
- package/package.json +1 -1
- package/sass/components/_sidenav.scss +194 -3
package/dist/index.esm.js
CHANGED
|
@@ -963,6 +963,18 @@ const iconPaths = {
|
|
|
963
963
|
'M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z', // chevron down
|
|
964
964
|
'M0 0h24v24H0z', // background
|
|
965
965
|
],
|
|
966
|
+
chevron_left: [
|
|
967
|
+
'M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z', // chevron left
|
|
968
|
+
'M0 0h24v24H0z', // background
|
|
969
|
+
],
|
|
970
|
+
chevron_right: [
|
|
971
|
+
'M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z', // chevron right
|
|
972
|
+
'M0 0h24v24H0z', // background
|
|
973
|
+
],
|
|
974
|
+
menu: [
|
|
975
|
+
'M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z', // hamburger menu
|
|
976
|
+
'M0 0h24v24H0z', // background
|
|
977
|
+
],
|
|
966
978
|
expand: [
|
|
967
979
|
'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z', // plus
|
|
968
980
|
'M0 0h24v24H0z', // background
|
|
@@ -971,6 +983,18 @@ const iconPaths = {
|
|
|
971
983
|
'M19 13H5v-2h14v2z', // minus
|
|
972
984
|
'M0 0h24v24H0z', // background
|
|
973
985
|
],
|
|
986
|
+
check: [
|
|
987
|
+
'M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z', // checkmark
|
|
988
|
+
'M0 0h24v24H0z', // background
|
|
989
|
+
],
|
|
990
|
+
radio_checked: [
|
|
991
|
+
'M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z', // radio button checked
|
|
992
|
+
'M0 0h24v24H0z', // background
|
|
993
|
+
],
|
|
994
|
+
radio_unchecked: [
|
|
995
|
+
'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z', // radio button unchecked
|
|
996
|
+
'M0 0h24v24H0z', // background
|
|
997
|
+
],
|
|
974
998
|
light_mode: [
|
|
975
999
|
'M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5M2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1m18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1M11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1m0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1M5.99 4.58a.996.996 0 0 0-1.41 0 .996.996 0 0 0 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41zm12.4 12.4a.996.996 0 0 0-1.41 0 .996.996 0 0 0 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0a.996.996 0 0 0 0-1.41zm1.06-11a.996.996 0 0 0 0-1.41.996.996 0 0 0-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0zM7.05 18.4a.996.996 0 0 0 0-1.41.996.996 0 0 0-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0z',
|
|
976
1000
|
'M0 0h24v24H0z', // background
|
|
@@ -7797,12 +7821,27 @@ const Sidenav = () => {
|
|
|
7797
7821
|
document.body.style.overflow = isOpen && mode === 'overlay' ? 'hidden' : '';
|
|
7798
7822
|
}
|
|
7799
7823
|
};
|
|
7824
|
+
const toggleExpanded = (attrs) => {
|
|
7825
|
+
const newExpandedState = !(attrs.isExpanded !== false);
|
|
7826
|
+
if (attrs.onExpandChange) {
|
|
7827
|
+
attrs.onExpandChange(newExpandedState);
|
|
7828
|
+
}
|
|
7829
|
+
};
|
|
7830
|
+
const toggleHamburger = (attrs) => {
|
|
7831
|
+
const newOpenState = !state.isOpen;
|
|
7832
|
+
if (attrs.onToggle) {
|
|
7833
|
+
attrs.onToggle(newOpenState);
|
|
7834
|
+
}
|
|
7835
|
+
};
|
|
7800
7836
|
return {
|
|
7801
7837
|
oninit: ({ attrs }) => {
|
|
7802
7838
|
state = {
|
|
7803
7839
|
id: attrs.id || uniqueId(),
|
|
7804
7840
|
isOpen: attrs.isOpen || false,
|
|
7805
7841
|
isAnimating: false,
|
|
7842
|
+
isExpanded: attrs.isExpanded !== false,
|
|
7843
|
+
activeItemIndex: null,
|
|
7844
|
+
selectedSubmenuItems: new Map(),
|
|
7806
7845
|
};
|
|
7807
7846
|
// Set up keyboard listener
|
|
7808
7847
|
if (typeof document !== 'undefined' && attrs.closeOnEscape !== false) {
|
|
@@ -7831,12 +7870,16 @@ const Sidenav = () => {
|
|
|
7831
7870
|
}
|
|
7832
7871
|
},
|
|
7833
7872
|
view: ({ attrs, children }) => {
|
|
7834
|
-
const { position = 'left', mode = 'overlay', width = 300, className = '', showBackdrop = true, animationDuration = 300, fixed = false, } = attrs;
|
|
7873
|
+
const { position = 'left', mode = 'overlay', width = 300, className = '', showBackdrop = true, animationDuration = 300, fixed = false, showHamburger = false, expandable = false, } = attrs;
|
|
7835
7874
|
const isOpen = state.isOpen;
|
|
7875
|
+
const collapsedWidth = 60;
|
|
7876
|
+
const isExpanded = attrs.isExpanded !== false;
|
|
7877
|
+
const currentWidth = expandable && !isExpanded ? collapsedWidth : width;
|
|
7836
7878
|
return [
|
|
7837
|
-
// Backdrop (using existing materialize class)
|
|
7879
|
+
// Backdrop (using existing materialize class) - only for overlay mode
|
|
7838
7880
|
showBackdrop &&
|
|
7839
7881
|
mode === 'overlay' &&
|
|
7882
|
+
!fixed &&
|
|
7840
7883
|
m('.sidenav-overlay', {
|
|
7841
7884
|
style: {
|
|
7842
7885
|
display: isOpen ? 'block' : 'none',
|
|
@@ -7847,49 +7890,206 @@ const Sidenav = () => {
|
|
|
7847
7890
|
// Sidenav (using existing materialize structure)
|
|
7848
7891
|
m('ul.sidenav', {
|
|
7849
7892
|
id: state.id,
|
|
7850
|
-
class: [
|
|
7893
|
+
class: [
|
|
7894
|
+
position === 'right' ? 'right-aligned' : '',
|
|
7895
|
+
fixed ? 'sidenav-fixed' : '',
|
|
7896
|
+
expandable && !isExpanded ? 'sidenav-collapsed' : '',
|
|
7897
|
+
className,
|
|
7898
|
+
]
|
|
7851
7899
|
.filter(Boolean)
|
|
7852
7900
|
.join(' ') || undefined,
|
|
7853
7901
|
style: {
|
|
7854
|
-
width: `${
|
|
7902
|
+
width: `${currentWidth}px`,
|
|
7855
7903
|
transform: isOpen ? 'translateX(0)' : position === 'left' ? 'translateX(-105%)' : 'translateX(105%)',
|
|
7856
7904
|
'transition-duration': `${animationDuration}ms`,
|
|
7905
|
+
'transition-property': 'transform, width',
|
|
7857
7906
|
},
|
|
7858
|
-
},
|
|
7907
|
+
}, [
|
|
7908
|
+
// Hamburger toggle button (inside sidenav, at the top)
|
|
7909
|
+
showHamburger &&
|
|
7910
|
+
m('li.sidenav-hamburger-item', {
|
|
7911
|
+
style: {
|
|
7912
|
+
display: 'flex',
|
|
7913
|
+
'justify-content': position === 'right' ? 'flex-end' : 'flex-start',
|
|
7914
|
+
'align-items': 'center',
|
|
7915
|
+
padding: '12px 16px',
|
|
7916
|
+
cursor: 'pointer',
|
|
7917
|
+
'border-bottom': '1px solid rgba(0,0,0,0.1)',
|
|
7918
|
+
},
|
|
7919
|
+
onclick: () => toggleHamburger(attrs),
|
|
7920
|
+
}, m(MaterialIcon, {
|
|
7921
|
+
name: 'menu',
|
|
7922
|
+
style: { width: '24px', height: '24px' },
|
|
7923
|
+
})),
|
|
7924
|
+
// Expand/collapse toggle button (if expandable, right below hamburger)
|
|
7925
|
+
expandable &&
|
|
7926
|
+
m('li.sidenav-expand-toggle', {
|
|
7927
|
+
style: {
|
|
7928
|
+
display: 'flex',
|
|
7929
|
+
'justify-content': position === 'right' ? 'flex-end' : 'flex-start',
|
|
7930
|
+
'align-items': 'center',
|
|
7931
|
+
padding: '12px 16px',
|
|
7932
|
+
cursor: 'pointer',
|
|
7933
|
+
'border-bottom': '1px solid rgba(0,0,0,0.1)',
|
|
7934
|
+
},
|
|
7935
|
+
onclick: () => toggleExpanded(attrs),
|
|
7936
|
+
}, m(MaterialIcon, {
|
|
7937
|
+
name: position === 'right'
|
|
7938
|
+
? (isExpanded ? 'chevron_right' : 'chevron_left')
|
|
7939
|
+
: (isExpanded ? 'chevron_left' : 'chevron_right'),
|
|
7940
|
+
style: { width: '24px', height: '24px' },
|
|
7941
|
+
})),
|
|
7942
|
+
// Children (menu items) - inject internal props
|
|
7943
|
+
Array.isArray(children)
|
|
7944
|
+
? children.map((child) => {
|
|
7945
|
+
if (child && typeof child === 'object' && 'tag' in child) {
|
|
7946
|
+
// Clone the vnode and add internal props
|
|
7947
|
+
return Object.assign(Object.assign({}, child), { attrs: Object.assign(Object.assign({}, child.attrs), { _isExpanded: isExpanded, _position: position }) });
|
|
7948
|
+
}
|
|
7949
|
+
return child;
|
|
7950
|
+
})
|
|
7951
|
+
: children,
|
|
7952
|
+
]),
|
|
7859
7953
|
];
|
|
7860
7954
|
},
|
|
7861
7955
|
};
|
|
7862
7956
|
};
|
|
7957
|
+
/**
|
|
7958
|
+
* Sidenav Submenu Item Component
|
|
7959
|
+
*/
|
|
7960
|
+
const NavbarSubItem = () => {
|
|
7961
|
+
return {
|
|
7962
|
+
view: ({ attrs }) => {
|
|
7963
|
+
const { text, icon, selected = false, value, onSelect, mode, isExpanded, position = 'left' } = attrs;
|
|
7964
|
+
const handleClick = () => {
|
|
7965
|
+
if (onSelect) {
|
|
7966
|
+
onSelect(value !== undefined ? value : text, !selected);
|
|
7967
|
+
}
|
|
7968
|
+
};
|
|
7969
|
+
const isRightAligned = position === 'right';
|
|
7970
|
+
const submenuContent = isRightAligned
|
|
7971
|
+
? [
|
|
7972
|
+
// Right-aligned: text on left, icons on right
|
|
7973
|
+
isExpanded && m('span', { style: { 'flex': '1', 'text-align': 'left' } }, text),
|
|
7974
|
+
icon && isExpanded && m('i.material-icons', { style: { 'font-size': '18px' } }, icon),
|
|
7975
|
+
m(MaterialIcon, {
|
|
7976
|
+
name: mode === 'checkbox' ? (selected ? 'check' : 'close') : selected ? 'radio_checked' : 'radio_unchecked',
|
|
7977
|
+
style: {
|
|
7978
|
+
width: '18px',
|
|
7979
|
+
height: '18px',
|
|
7980
|
+
opacity: mode === 'checkbox' && !selected ? '0.3' : '1',
|
|
7981
|
+
},
|
|
7982
|
+
}),
|
|
7983
|
+
]
|
|
7984
|
+
: [
|
|
7985
|
+
// Left-aligned: indicator on left, text and icon on right
|
|
7986
|
+
m(MaterialIcon, {
|
|
7987
|
+
name: mode === 'checkbox' ? (selected ? 'check' : 'close') : selected ? 'radio_checked' : 'radio_unchecked',
|
|
7988
|
+
style: {
|
|
7989
|
+
width: '18px',
|
|
7990
|
+
height: '18px',
|
|
7991
|
+
opacity: mode === 'checkbox' && !selected ? '0.3' : '1',
|
|
7992
|
+
},
|
|
7993
|
+
}),
|
|
7994
|
+
icon && isExpanded && m('i.material-icons', { style: { 'font-size': '18px', 'margin-left': '8px' } }, icon),
|
|
7995
|
+
isExpanded && m('span', { style: { 'margin-left': icon ? '8px' : '8px' } }, text),
|
|
7996
|
+
];
|
|
7997
|
+
return m('li.sidenav-subitem', {
|
|
7998
|
+
class: selected ? 'selected' : '',
|
|
7999
|
+
style: {
|
|
8000
|
+
padding: isExpanded ? '8px 16px 8px 48px' : '8px 16px',
|
|
8001
|
+
cursor: 'pointer',
|
|
8002
|
+
display: 'flex',
|
|
8003
|
+
'align-items': 'center',
|
|
8004
|
+
gap: '8px',
|
|
8005
|
+
'font-size': '0.9em',
|
|
8006
|
+
'justify-content': isRightAligned ? 'space-between' : 'flex-start',
|
|
8007
|
+
},
|
|
8008
|
+
onclick: handleClick,
|
|
8009
|
+
}, submenuContent);
|
|
8010
|
+
},
|
|
8011
|
+
};
|
|
8012
|
+
};
|
|
7863
8013
|
/**
|
|
7864
8014
|
* Sidenav Item Component
|
|
7865
8015
|
* Individual items for the sidenav menu
|
|
7866
8016
|
*/
|
|
7867
8017
|
const SidenavItem = () => {
|
|
8018
|
+
let isSubmenuOpen = false;
|
|
7868
8019
|
return {
|
|
7869
8020
|
view: ({ attrs, children }) => {
|
|
7870
|
-
const { text, icon, active = false, disabled = false, onclick, href, className = '', divider = false, subheader = false, } = attrs;
|
|
8021
|
+
const { text, icon, active = false, disabled = false, onclick, href, className = '', divider = false, subheader = false, submenu = [], submenuMode = 'checkbox', } = attrs;
|
|
7871
8022
|
if (divider) {
|
|
7872
8023
|
return m('li.divider');
|
|
7873
8024
|
}
|
|
7874
8025
|
if (subheader) {
|
|
7875
8026
|
return m('li.subheader', text || children);
|
|
7876
8027
|
}
|
|
7877
|
-
const
|
|
7878
|
-
const
|
|
7879
|
-
|
|
7880
|
-
|
|
8028
|
+
const hasSubmenu = submenu && submenu.length > 0;
|
|
8029
|
+
const itemClasses = [
|
|
8030
|
+
active ? 'active' : '',
|
|
8031
|
+
disabled ? 'disabled' : '',
|
|
8032
|
+
hasSubmenu ? 'has-submenu' : '',
|
|
8033
|
+
className,
|
|
8034
|
+
]
|
|
8035
|
+
.filter(Boolean)
|
|
8036
|
+
.join(' ') || undefined;
|
|
8037
|
+
const handleMainClick = (e) => {
|
|
8038
|
+
e.preventDefault();
|
|
8039
|
+
if (hasSubmenu) {
|
|
8040
|
+
isSubmenuOpen = active ? !isSubmenuOpen : true;
|
|
8041
|
+
}
|
|
8042
|
+
if (onclick && !disabled) {
|
|
8043
|
+
onclick(e);
|
|
8044
|
+
}
|
|
8045
|
+
};
|
|
8046
|
+
// Get internal props passed from parent Sidenav
|
|
8047
|
+
const isExpanded = attrs._isExpanded !== false;
|
|
8048
|
+
const position = attrs._position || 'left';
|
|
8049
|
+
const isRightAligned = position === 'right';
|
|
8050
|
+
// In expanded mode, icons are at the outside edge
|
|
8051
|
+
// In collapsed mode, icons are centered
|
|
8052
|
+
const content = isRightAligned
|
|
8053
|
+
? [
|
|
8054
|
+
// Right-aligned: text on left, icon on right
|
|
8055
|
+
isExpanded && m('span.sidenav-item-text', { style: { 'flex': '1', 'text-align': 'left', 'margin-right': '8px' } }, text || children),
|
|
8056
|
+
m('i.material-icons', { style: { 'min-width': '24px', 'width': '24px' } }, icon || ''),
|
|
8057
|
+
]
|
|
8058
|
+
: [
|
|
8059
|
+
// Left-aligned: icon on left, text on right
|
|
8060
|
+
m('i.material-icons', { style: { 'min-width': '24px', 'width': '24px' } }, icon || ''),
|
|
8061
|
+
isExpanded && m('span.sidenav-item-text', { style: { 'margin-left': '8px', 'flex': '1' } }, text || children),
|
|
8062
|
+
];
|
|
8063
|
+
const linkStyle = {
|
|
8064
|
+
display: 'flex',
|
|
8065
|
+
'align-items': 'center',
|
|
8066
|
+
padding: isExpanded ? '12px 16px' : '12px 18px',
|
|
8067
|
+
'justify-content': isExpanded ? (isRightAligned ? 'flex-end' : 'flex-start') : 'center',
|
|
8068
|
+
};
|
|
8069
|
+
const mainItem = href && !disabled
|
|
8070
|
+
? m('li', { class: itemClasses }, [
|
|
7881
8071
|
m('a', {
|
|
7882
8072
|
href,
|
|
7883
|
-
onclick:
|
|
8073
|
+
onclick: handleMainClick,
|
|
8074
|
+
style: linkStyle,
|
|
8075
|
+
}, content),
|
|
8076
|
+
])
|
|
8077
|
+
: m('li', { class: itemClasses }, [
|
|
8078
|
+
m('a', {
|
|
8079
|
+
onclick: handleMainClick,
|
|
8080
|
+
href: '#!',
|
|
8081
|
+
style: linkStyle,
|
|
7884
8082
|
}, content),
|
|
7885
8083
|
]);
|
|
8084
|
+
// Return main item with submenu if applicable
|
|
8085
|
+
if (hasSubmenu && active && isSubmenuOpen) {
|
|
8086
|
+
return [
|
|
8087
|
+
mainItem,
|
|
8088
|
+
submenu.map((subItem) => m(NavbarSubItem, Object.assign(Object.assign({}, subItem), { mode: submenuMode, isExpanded,
|
|
8089
|
+
position }))),
|
|
8090
|
+
];
|
|
7886
8091
|
}
|
|
7887
|
-
return
|
|
7888
|
-
m('a', {
|
|
7889
|
-
onclick: disabled ? undefined : onclick,
|
|
7890
|
-
href: '#!',
|
|
7891
|
-
}, content),
|
|
7892
|
-
]);
|
|
8092
|
+
return mainItem;
|
|
7893
8093
|
},
|
|
7894
8094
|
};
|
|
7895
8095
|
};
|
package/dist/index.js
CHANGED
|
@@ -965,6 +965,18 @@ const iconPaths = {
|
|
|
965
965
|
'M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z', // chevron down
|
|
966
966
|
'M0 0h24v24H0z', // background
|
|
967
967
|
],
|
|
968
|
+
chevron_left: [
|
|
969
|
+
'M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z', // chevron left
|
|
970
|
+
'M0 0h24v24H0z', // background
|
|
971
|
+
],
|
|
972
|
+
chevron_right: [
|
|
973
|
+
'M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z', // chevron right
|
|
974
|
+
'M0 0h24v24H0z', // background
|
|
975
|
+
],
|
|
976
|
+
menu: [
|
|
977
|
+
'M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z', // hamburger menu
|
|
978
|
+
'M0 0h24v24H0z', // background
|
|
979
|
+
],
|
|
968
980
|
expand: [
|
|
969
981
|
'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z', // plus
|
|
970
982
|
'M0 0h24v24H0z', // background
|
|
@@ -973,6 +985,18 @@ const iconPaths = {
|
|
|
973
985
|
'M19 13H5v-2h14v2z', // minus
|
|
974
986
|
'M0 0h24v24H0z', // background
|
|
975
987
|
],
|
|
988
|
+
check: [
|
|
989
|
+
'M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z', // checkmark
|
|
990
|
+
'M0 0h24v24H0z', // background
|
|
991
|
+
],
|
|
992
|
+
radio_checked: [
|
|
993
|
+
'M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z', // radio button checked
|
|
994
|
+
'M0 0h24v24H0z', // background
|
|
995
|
+
],
|
|
996
|
+
radio_unchecked: [
|
|
997
|
+
'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z', // radio button unchecked
|
|
998
|
+
'M0 0h24v24H0z', // background
|
|
999
|
+
],
|
|
976
1000
|
light_mode: [
|
|
977
1001
|
'M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5M2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1m18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1M11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1m0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1M5.99 4.58a.996.996 0 0 0-1.41 0 .996.996 0 0 0 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41zm12.4 12.4a.996.996 0 0 0-1.41 0 .996.996 0 0 0 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0a.996.996 0 0 0 0-1.41zm1.06-11a.996.996 0 0 0 0-1.41.996.996 0 0 0-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0zM7.05 18.4a.996.996 0 0 0 0-1.41.996.996 0 0 0-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0z',
|
|
978
1002
|
'M0 0h24v24H0z', // background
|
|
@@ -7799,12 +7823,27 @@ const Sidenav = () => {
|
|
|
7799
7823
|
document.body.style.overflow = isOpen && mode === 'overlay' ? 'hidden' : '';
|
|
7800
7824
|
}
|
|
7801
7825
|
};
|
|
7826
|
+
const toggleExpanded = (attrs) => {
|
|
7827
|
+
const newExpandedState = !(attrs.isExpanded !== false);
|
|
7828
|
+
if (attrs.onExpandChange) {
|
|
7829
|
+
attrs.onExpandChange(newExpandedState);
|
|
7830
|
+
}
|
|
7831
|
+
};
|
|
7832
|
+
const toggleHamburger = (attrs) => {
|
|
7833
|
+
const newOpenState = !state.isOpen;
|
|
7834
|
+
if (attrs.onToggle) {
|
|
7835
|
+
attrs.onToggle(newOpenState);
|
|
7836
|
+
}
|
|
7837
|
+
};
|
|
7802
7838
|
return {
|
|
7803
7839
|
oninit: ({ attrs }) => {
|
|
7804
7840
|
state = {
|
|
7805
7841
|
id: attrs.id || uniqueId(),
|
|
7806
7842
|
isOpen: attrs.isOpen || false,
|
|
7807
7843
|
isAnimating: false,
|
|
7844
|
+
isExpanded: attrs.isExpanded !== false,
|
|
7845
|
+
activeItemIndex: null,
|
|
7846
|
+
selectedSubmenuItems: new Map(),
|
|
7808
7847
|
};
|
|
7809
7848
|
// Set up keyboard listener
|
|
7810
7849
|
if (typeof document !== 'undefined' && attrs.closeOnEscape !== false) {
|
|
@@ -7833,12 +7872,16 @@ const Sidenav = () => {
|
|
|
7833
7872
|
}
|
|
7834
7873
|
},
|
|
7835
7874
|
view: ({ attrs, children }) => {
|
|
7836
|
-
const { position = 'left', mode = 'overlay', width = 300, className = '', showBackdrop = true, animationDuration = 300, fixed = false, } = attrs;
|
|
7875
|
+
const { position = 'left', mode = 'overlay', width = 300, className = '', showBackdrop = true, animationDuration = 300, fixed = false, showHamburger = false, expandable = false, } = attrs;
|
|
7837
7876
|
const isOpen = state.isOpen;
|
|
7877
|
+
const collapsedWidth = 60;
|
|
7878
|
+
const isExpanded = attrs.isExpanded !== false;
|
|
7879
|
+
const currentWidth = expandable && !isExpanded ? collapsedWidth : width;
|
|
7838
7880
|
return [
|
|
7839
|
-
// Backdrop (using existing materialize class)
|
|
7881
|
+
// Backdrop (using existing materialize class) - only for overlay mode
|
|
7840
7882
|
showBackdrop &&
|
|
7841
7883
|
mode === 'overlay' &&
|
|
7884
|
+
!fixed &&
|
|
7842
7885
|
m('.sidenav-overlay', {
|
|
7843
7886
|
style: {
|
|
7844
7887
|
display: isOpen ? 'block' : 'none',
|
|
@@ -7849,49 +7892,206 @@ const Sidenav = () => {
|
|
|
7849
7892
|
// Sidenav (using existing materialize structure)
|
|
7850
7893
|
m('ul.sidenav', {
|
|
7851
7894
|
id: state.id,
|
|
7852
|
-
class: [
|
|
7895
|
+
class: [
|
|
7896
|
+
position === 'right' ? 'right-aligned' : '',
|
|
7897
|
+
fixed ? 'sidenav-fixed' : '',
|
|
7898
|
+
expandable && !isExpanded ? 'sidenav-collapsed' : '',
|
|
7899
|
+
className,
|
|
7900
|
+
]
|
|
7853
7901
|
.filter(Boolean)
|
|
7854
7902
|
.join(' ') || undefined,
|
|
7855
7903
|
style: {
|
|
7856
|
-
width: `${
|
|
7904
|
+
width: `${currentWidth}px`,
|
|
7857
7905
|
transform: isOpen ? 'translateX(0)' : position === 'left' ? 'translateX(-105%)' : 'translateX(105%)',
|
|
7858
7906
|
'transition-duration': `${animationDuration}ms`,
|
|
7907
|
+
'transition-property': 'transform, width',
|
|
7859
7908
|
},
|
|
7860
|
-
},
|
|
7909
|
+
}, [
|
|
7910
|
+
// Hamburger toggle button (inside sidenav, at the top)
|
|
7911
|
+
showHamburger &&
|
|
7912
|
+
m('li.sidenav-hamburger-item', {
|
|
7913
|
+
style: {
|
|
7914
|
+
display: 'flex',
|
|
7915
|
+
'justify-content': position === 'right' ? 'flex-end' : 'flex-start',
|
|
7916
|
+
'align-items': 'center',
|
|
7917
|
+
padding: '12px 16px',
|
|
7918
|
+
cursor: 'pointer',
|
|
7919
|
+
'border-bottom': '1px solid rgba(0,0,0,0.1)',
|
|
7920
|
+
},
|
|
7921
|
+
onclick: () => toggleHamburger(attrs),
|
|
7922
|
+
}, m(MaterialIcon, {
|
|
7923
|
+
name: 'menu',
|
|
7924
|
+
style: { width: '24px', height: '24px' },
|
|
7925
|
+
})),
|
|
7926
|
+
// Expand/collapse toggle button (if expandable, right below hamburger)
|
|
7927
|
+
expandable &&
|
|
7928
|
+
m('li.sidenav-expand-toggle', {
|
|
7929
|
+
style: {
|
|
7930
|
+
display: 'flex',
|
|
7931
|
+
'justify-content': position === 'right' ? 'flex-end' : 'flex-start',
|
|
7932
|
+
'align-items': 'center',
|
|
7933
|
+
padding: '12px 16px',
|
|
7934
|
+
cursor: 'pointer',
|
|
7935
|
+
'border-bottom': '1px solid rgba(0,0,0,0.1)',
|
|
7936
|
+
},
|
|
7937
|
+
onclick: () => toggleExpanded(attrs),
|
|
7938
|
+
}, m(MaterialIcon, {
|
|
7939
|
+
name: position === 'right'
|
|
7940
|
+
? (isExpanded ? 'chevron_right' : 'chevron_left')
|
|
7941
|
+
: (isExpanded ? 'chevron_left' : 'chevron_right'),
|
|
7942
|
+
style: { width: '24px', height: '24px' },
|
|
7943
|
+
})),
|
|
7944
|
+
// Children (menu items) - inject internal props
|
|
7945
|
+
Array.isArray(children)
|
|
7946
|
+
? children.map((child) => {
|
|
7947
|
+
if (child && typeof child === 'object' && 'tag' in child) {
|
|
7948
|
+
// Clone the vnode and add internal props
|
|
7949
|
+
return Object.assign(Object.assign({}, child), { attrs: Object.assign(Object.assign({}, child.attrs), { _isExpanded: isExpanded, _position: position }) });
|
|
7950
|
+
}
|
|
7951
|
+
return child;
|
|
7952
|
+
})
|
|
7953
|
+
: children,
|
|
7954
|
+
]),
|
|
7861
7955
|
];
|
|
7862
7956
|
},
|
|
7863
7957
|
};
|
|
7864
7958
|
};
|
|
7959
|
+
/**
|
|
7960
|
+
* Sidenav Submenu Item Component
|
|
7961
|
+
*/
|
|
7962
|
+
const NavbarSubItem = () => {
|
|
7963
|
+
return {
|
|
7964
|
+
view: ({ attrs }) => {
|
|
7965
|
+
const { text, icon, selected = false, value, onSelect, mode, isExpanded, position = 'left' } = attrs;
|
|
7966
|
+
const handleClick = () => {
|
|
7967
|
+
if (onSelect) {
|
|
7968
|
+
onSelect(value !== undefined ? value : text, !selected);
|
|
7969
|
+
}
|
|
7970
|
+
};
|
|
7971
|
+
const isRightAligned = position === 'right';
|
|
7972
|
+
const submenuContent = isRightAligned
|
|
7973
|
+
? [
|
|
7974
|
+
// Right-aligned: text on left, icons on right
|
|
7975
|
+
isExpanded && m('span', { style: { 'flex': '1', 'text-align': 'left' } }, text),
|
|
7976
|
+
icon && isExpanded && m('i.material-icons', { style: { 'font-size': '18px' } }, icon),
|
|
7977
|
+
m(MaterialIcon, {
|
|
7978
|
+
name: mode === 'checkbox' ? (selected ? 'check' : 'close') : selected ? 'radio_checked' : 'radio_unchecked',
|
|
7979
|
+
style: {
|
|
7980
|
+
width: '18px',
|
|
7981
|
+
height: '18px',
|
|
7982
|
+
opacity: mode === 'checkbox' && !selected ? '0.3' : '1',
|
|
7983
|
+
},
|
|
7984
|
+
}),
|
|
7985
|
+
]
|
|
7986
|
+
: [
|
|
7987
|
+
// Left-aligned: indicator on left, text and icon on right
|
|
7988
|
+
m(MaterialIcon, {
|
|
7989
|
+
name: mode === 'checkbox' ? (selected ? 'check' : 'close') : selected ? 'radio_checked' : 'radio_unchecked',
|
|
7990
|
+
style: {
|
|
7991
|
+
width: '18px',
|
|
7992
|
+
height: '18px',
|
|
7993
|
+
opacity: mode === 'checkbox' && !selected ? '0.3' : '1',
|
|
7994
|
+
},
|
|
7995
|
+
}),
|
|
7996
|
+
icon && isExpanded && m('i.material-icons', { style: { 'font-size': '18px', 'margin-left': '8px' } }, icon),
|
|
7997
|
+
isExpanded && m('span', { style: { 'margin-left': icon ? '8px' : '8px' } }, text),
|
|
7998
|
+
];
|
|
7999
|
+
return m('li.sidenav-subitem', {
|
|
8000
|
+
class: selected ? 'selected' : '',
|
|
8001
|
+
style: {
|
|
8002
|
+
padding: isExpanded ? '8px 16px 8px 48px' : '8px 16px',
|
|
8003
|
+
cursor: 'pointer',
|
|
8004
|
+
display: 'flex',
|
|
8005
|
+
'align-items': 'center',
|
|
8006
|
+
gap: '8px',
|
|
8007
|
+
'font-size': '0.9em',
|
|
8008
|
+
'justify-content': isRightAligned ? 'space-between' : 'flex-start',
|
|
8009
|
+
},
|
|
8010
|
+
onclick: handleClick,
|
|
8011
|
+
}, submenuContent);
|
|
8012
|
+
},
|
|
8013
|
+
};
|
|
8014
|
+
};
|
|
7865
8015
|
/**
|
|
7866
8016
|
* Sidenav Item Component
|
|
7867
8017
|
* Individual items for the sidenav menu
|
|
7868
8018
|
*/
|
|
7869
8019
|
const SidenavItem = () => {
|
|
8020
|
+
let isSubmenuOpen = false;
|
|
7870
8021
|
return {
|
|
7871
8022
|
view: ({ attrs, children }) => {
|
|
7872
|
-
const { text, icon, active = false, disabled = false, onclick, href, className = '', divider = false, subheader = false, } = attrs;
|
|
8023
|
+
const { text, icon, active = false, disabled = false, onclick, href, className = '', divider = false, subheader = false, submenu = [], submenuMode = 'checkbox', } = attrs;
|
|
7873
8024
|
if (divider) {
|
|
7874
8025
|
return m('li.divider');
|
|
7875
8026
|
}
|
|
7876
8027
|
if (subheader) {
|
|
7877
8028
|
return m('li.subheader', text || children);
|
|
7878
8029
|
}
|
|
7879
|
-
const
|
|
7880
|
-
const
|
|
7881
|
-
|
|
7882
|
-
|
|
8030
|
+
const hasSubmenu = submenu && submenu.length > 0;
|
|
8031
|
+
const itemClasses = [
|
|
8032
|
+
active ? 'active' : '',
|
|
8033
|
+
disabled ? 'disabled' : '',
|
|
8034
|
+
hasSubmenu ? 'has-submenu' : '',
|
|
8035
|
+
className,
|
|
8036
|
+
]
|
|
8037
|
+
.filter(Boolean)
|
|
8038
|
+
.join(' ') || undefined;
|
|
8039
|
+
const handleMainClick = (e) => {
|
|
8040
|
+
e.preventDefault();
|
|
8041
|
+
if (hasSubmenu) {
|
|
8042
|
+
isSubmenuOpen = active ? !isSubmenuOpen : true;
|
|
8043
|
+
}
|
|
8044
|
+
if (onclick && !disabled) {
|
|
8045
|
+
onclick(e);
|
|
8046
|
+
}
|
|
8047
|
+
};
|
|
8048
|
+
// Get internal props passed from parent Sidenav
|
|
8049
|
+
const isExpanded = attrs._isExpanded !== false;
|
|
8050
|
+
const position = attrs._position || 'left';
|
|
8051
|
+
const isRightAligned = position === 'right';
|
|
8052
|
+
// In expanded mode, icons are at the outside edge
|
|
8053
|
+
// In collapsed mode, icons are centered
|
|
8054
|
+
const content = isRightAligned
|
|
8055
|
+
? [
|
|
8056
|
+
// Right-aligned: text on left, icon on right
|
|
8057
|
+
isExpanded && m('span.sidenav-item-text', { style: { 'flex': '1', 'text-align': 'left', 'margin-right': '8px' } }, text || children),
|
|
8058
|
+
m('i.material-icons', { style: { 'min-width': '24px', 'width': '24px' } }, icon || ''),
|
|
8059
|
+
]
|
|
8060
|
+
: [
|
|
8061
|
+
// Left-aligned: icon on left, text on right
|
|
8062
|
+
m('i.material-icons', { style: { 'min-width': '24px', 'width': '24px' } }, icon || ''),
|
|
8063
|
+
isExpanded && m('span.sidenav-item-text', { style: { 'margin-left': '8px', 'flex': '1' } }, text || children),
|
|
8064
|
+
];
|
|
8065
|
+
const linkStyle = {
|
|
8066
|
+
display: 'flex',
|
|
8067
|
+
'align-items': 'center',
|
|
8068
|
+
padding: isExpanded ? '12px 16px' : '12px 18px',
|
|
8069
|
+
'justify-content': isExpanded ? (isRightAligned ? 'flex-end' : 'flex-start') : 'center',
|
|
8070
|
+
};
|
|
8071
|
+
const mainItem = href && !disabled
|
|
8072
|
+
? m('li', { class: itemClasses }, [
|
|
7883
8073
|
m('a', {
|
|
7884
8074
|
href,
|
|
7885
|
-
onclick:
|
|
8075
|
+
onclick: handleMainClick,
|
|
8076
|
+
style: linkStyle,
|
|
8077
|
+
}, content),
|
|
8078
|
+
])
|
|
8079
|
+
: m('li', { class: itemClasses }, [
|
|
8080
|
+
m('a', {
|
|
8081
|
+
onclick: handleMainClick,
|
|
8082
|
+
href: '#!',
|
|
8083
|
+
style: linkStyle,
|
|
7886
8084
|
}, content),
|
|
7887
8085
|
]);
|
|
8086
|
+
// Return main item with submenu if applicable
|
|
8087
|
+
if (hasSubmenu && active && isSubmenuOpen) {
|
|
8088
|
+
return [
|
|
8089
|
+
mainItem,
|
|
8090
|
+
submenu.map((subItem) => m(NavbarSubItem, Object.assign(Object.assign({}, subItem), { mode: submenuMode, isExpanded,
|
|
8091
|
+
position }))),
|
|
8092
|
+
];
|
|
7888
8093
|
}
|
|
7889
|
-
return
|
|
7890
|
-
m('a', {
|
|
7891
|
-
onclick: disabled ? undefined : onclick,
|
|
7892
|
-
href: '#!',
|
|
7893
|
-
}, content),
|
|
7894
|
-
]);
|
|
8094
|
+
return mainItem;
|
|
7895
8095
|
},
|
|
7896
8096
|
};
|
|
7897
8097
|
};
|