mithril-materialized 3.4.4 → 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 +218 -17
- package/dist/index.js +218 -17
- package/dist/index.min.css +1 -1
- package/dist/index.umd.js +218 -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
|
@@ -264,6 +264,7 @@ const Autocomplete = () => {
|
|
|
264
264
|
state.isOpen = false;
|
|
265
265
|
state.selectedIndex = -1;
|
|
266
266
|
}
|
|
267
|
+
m.redraw();
|
|
267
268
|
};
|
|
268
269
|
const getDropdownStyles = () => {
|
|
269
270
|
if (!state.inputElement) {
|
|
@@ -962,6 +963,18 @@ const iconPaths = {
|
|
|
962
963
|
'M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z', // chevron down
|
|
963
964
|
'M0 0h24v24H0z', // background
|
|
964
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
|
+
],
|
|
965
978
|
expand: [
|
|
966
979
|
'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z', // plus
|
|
967
980
|
'M0 0h24v24H0z', // background
|
|
@@ -970,6 +983,18 @@ const iconPaths = {
|
|
|
970
983
|
'M19 13H5v-2h14v2z', // minus
|
|
971
984
|
'M0 0h24v24H0z', // background
|
|
972
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
|
+
],
|
|
973
998
|
light_mode: [
|
|
974
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',
|
|
975
1000
|
'M0 0h24v24H0z', // background
|
|
@@ -7796,12 +7821,27 @@ const Sidenav = () => {
|
|
|
7796
7821
|
document.body.style.overflow = isOpen && mode === 'overlay' ? 'hidden' : '';
|
|
7797
7822
|
}
|
|
7798
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
|
+
};
|
|
7799
7836
|
return {
|
|
7800
7837
|
oninit: ({ attrs }) => {
|
|
7801
7838
|
state = {
|
|
7802
7839
|
id: attrs.id || uniqueId(),
|
|
7803
7840
|
isOpen: attrs.isOpen || false,
|
|
7804
7841
|
isAnimating: false,
|
|
7842
|
+
isExpanded: attrs.isExpanded !== false,
|
|
7843
|
+
activeItemIndex: null,
|
|
7844
|
+
selectedSubmenuItems: new Map(),
|
|
7805
7845
|
};
|
|
7806
7846
|
// Set up keyboard listener
|
|
7807
7847
|
if (typeof document !== 'undefined' && attrs.closeOnEscape !== false) {
|
|
@@ -7830,12 +7870,16 @@ const Sidenav = () => {
|
|
|
7830
7870
|
}
|
|
7831
7871
|
},
|
|
7832
7872
|
view: ({ attrs, children }) => {
|
|
7833
|
-
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;
|
|
7834
7874
|
const isOpen = state.isOpen;
|
|
7875
|
+
const collapsedWidth = 60;
|
|
7876
|
+
const isExpanded = attrs.isExpanded !== false;
|
|
7877
|
+
const currentWidth = expandable && !isExpanded ? collapsedWidth : width;
|
|
7835
7878
|
return [
|
|
7836
|
-
// Backdrop (using existing materialize class)
|
|
7879
|
+
// Backdrop (using existing materialize class) - only for overlay mode
|
|
7837
7880
|
showBackdrop &&
|
|
7838
7881
|
mode === 'overlay' &&
|
|
7882
|
+
!fixed &&
|
|
7839
7883
|
m('.sidenav-overlay', {
|
|
7840
7884
|
style: {
|
|
7841
7885
|
display: isOpen ? 'block' : 'none',
|
|
@@ -7846,49 +7890,206 @@ const Sidenav = () => {
|
|
|
7846
7890
|
// Sidenav (using existing materialize structure)
|
|
7847
7891
|
m('ul.sidenav', {
|
|
7848
7892
|
id: state.id,
|
|
7849
|
-
class: [
|
|
7893
|
+
class: [
|
|
7894
|
+
position === 'right' ? 'right-aligned' : '',
|
|
7895
|
+
fixed ? 'sidenav-fixed' : '',
|
|
7896
|
+
expandable && !isExpanded ? 'sidenav-collapsed' : '',
|
|
7897
|
+
className,
|
|
7898
|
+
]
|
|
7850
7899
|
.filter(Boolean)
|
|
7851
7900
|
.join(' ') || undefined,
|
|
7852
7901
|
style: {
|
|
7853
|
-
width: `${
|
|
7902
|
+
width: `${currentWidth}px`,
|
|
7854
7903
|
transform: isOpen ? 'translateX(0)' : position === 'left' ? 'translateX(-105%)' : 'translateX(105%)',
|
|
7855
7904
|
'transition-duration': `${animationDuration}ms`,
|
|
7905
|
+
'transition-property': 'transform, width',
|
|
7856
7906
|
},
|
|
7857
|
-
},
|
|
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
|
+
]),
|
|
7858
7953
|
];
|
|
7859
7954
|
},
|
|
7860
7955
|
};
|
|
7861
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
|
+
};
|
|
7862
8013
|
/**
|
|
7863
8014
|
* Sidenav Item Component
|
|
7864
8015
|
* Individual items for the sidenav menu
|
|
7865
8016
|
*/
|
|
7866
8017
|
const SidenavItem = () => {
|
|
8018
|
+
let isSubmenuOpen = false;
|
|
7867
8019
|
return {
|
|
7868
8020
|
view: ({ attrs, children }) => {
|
|
7869
|
-
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;
|
|
7870
8022
|
if (divider) {
|
|
7871
8023
|
return m('li.divider');
|
|
7872
8024
|
}
|
|
7873
8025
|
if (subheader) {
|
|
7874
8026
|
return m('li.subheader', text || children);
|
|
7875
8027
|
}
|
|
7876
|
-
const
|
|
7877
|
-
const
|
|
7878
|
-
|
|
7879
|
-
|
|
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 }, [
|
|
7880
8071
|
m('a', {
|
|
7881
8072
|
href,
|
|
7882
|
-
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,
|
|
7883
8082
|
}, content),
|
|
7884
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
|
+
];
|
|
7885
8091
|
}
|
|
7886
|
-
return
|
|
7887
|
-
m('a', {
|
|
7888
|
-
onclick: disabled ? undefined : onclick,
|
|
7889
|
-
href: '#!',
|
|
7890
|
-
}, content),
|
|
7891
|
-
]);
|
|
8092
|
+
return mainItem;
|
|
7892
8093
|
},
|
|
7893
8094
|
};
|
|
7894
8095
|
};
|
package/dist/index.js
CHANGED
|
@@ -266,6 +266,7 @@ const Autocomplete = () => {
|
|
|
266
266
|
state.isOpen = false;
|
|
267
267
|
state.selectedIndex = -1;
|
|
268
268
|
}
|
|
269
|
+
m.redraw();
|
|
269
270
|
};
|
|
270
271
|
const getDropdownStyles = () => {
|
|
271
272
|
if (!state.inputElement) {
|
|
@@ -964,6 +965,18 @@ const iconPaths = {
|
|
|
964
965
|
'M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z', // chevron down
|
|
965
966
|
'M0 0h24v24H0z', // background
|
|
966
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
|
+
],
|
|
967
980
|
expand: [
|
|
968
981
|
'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z', // plus
|
|
969
982
|
'M0 0h24v24H0z', // background
|
|
@@ -972,6 +985,18 @@ const iconPaths = {
|
|
|
972
985
|
'M19 13H5v-2h14v2z', // minus
|
|
973
986
|
'M0 0h24v24H0z', // background
|
|
974
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
|
+
],
|
|
975
1000
|
light_mode: [
|
|
976
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',
|
|
977
1002
|
'M0 0h24v24H0z', // background
|
|
@@ -7798,12 +7823,27 @@ const Sidenav = () => {
|
|
|
7798
7823
|
document.body.style.overflow = isOpen && mode === 'overlay' ? 'hidden' : '';
|
|
7799
7824
|
}
|
|
7800
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
|
+
};
|
|
7801
7838
|
return {
|
|
7802
7839
|
oninit: ({ attrs }) => {
|
|
7803
7840
|
state = {
|
|
7804
7841
|
id: attrs.id || uniqueId(),
|
|
7805
7842
|
isOpen: attrs.isOpen || false,
|
|
7806
7843
|
isAnimating: false,
|
|
7844
|
+
isExpanded: attrs.isExpanded !== false,
|
|
7845
|
+
activeItemIndex: null,
|
|
7846
|
+
selectedSubmenuItems: new Map(),
|
|
7807
7847
|
};
|
|
7808
7848
|
// Set up keyboard listener
|
|
7809
7849
|
if (typeof document !== 'undefined' && attrs.closeOnEscape !== false) {
|
|
@@ -7832,12 +7872,16 @@ const Sidenav = () => {
|
|
|
7832
7872
|
}
|
|
7833
7873
|
},
|
|
7834
7874
|
view: ({ attrs, children }) => {
|
|
7835
|
-
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;
|
|
7836
7876
|
const isOpen = state.isOpen;
|
|
7877
|
+
const collapsedWidth = 60;
|
|
7878
|
+
const isExpanded = attrs.isExpanded !== false;
|
|
7879
|
+
const currentWidth = expandable && !isExpanded ? collapsedWidth : width;
|
|
7837
7880
|
return [
|
|
7838
|
-
// Backdrop (using existing materialize class)
|
|
7881
|
+
// Backdrop (using existing materialize class) - only for overlay mode
|
|
7839
7882
|
showBackdrop &&
|
|
7840
7883
|
mode === 'overlay' &&
|
|
7884
|
+
!fixed &&
|
|
7841
7885
|
m('.sidenav-overlay', {
|
|
7842
7886
|
style: {
|
|
7843
7887
|
display: isOpen ? 'block' : 'none',
|
|
@@ -7848,49 +7892,206 @@ const Sidenav = () => {
|
|
|
7848
7892
|
// Sidenav (using existing materialize structure)
|
|
7849
7893
|
m('ul.sidenav', {
|
|
7850
7894
|
id: state.id,
|
|
7851
|
-
class: [
|
|
7895
|
+
class: [
|
|
7896
|
+
position === 'right' ? 'right-aligned' : '',
|
|
7897
|
+
fixed ? 'sidenav-fixed' : '',
|
|
7898
|
+
expandable && !isExpanded ? 'sidenav-collapsed' : '',
|
|
7899
|
+
className,
|
|
7900
|
+
]
|
|
7852
7901
|
.filter(Boolean)
|
|
7853
7902
|
.join(' ') || undefined,
|
|
7854
7903
|
style: {
|
|
7855
|
-
width: `${
|
|
7904
|
+
width: `${currentWidth}px`,
|
|
7856
7905
|
transform: isOpen ? 'translateX(0)' : position === 'left' ? 'translateX(-105%)' : 'translateX(105%)',
|
|
7857
7906
|
'transition-duration': `${animationDuration}ms`,
|
|
7907
|
+
'transition-property': 'transform, width',
|
|
7858
7908
|
},
|
|
7859
|
-
},
|
|
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
|
+
]),
|
|
7860
7955
|
];
|
|
7861
7956
|
},
|
|
7862
7957
|
};
|
|
7863
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
|
+
};
|
|
7864
8015
|
/**
|
|
7865
8016
|
* Sidenav Item Component
|
|
7866
8017
|
* Individual items for the sidenav menu
|
|
7867
8018
|
*/
|
|
7868
8019
|
const SidenavItem = () => {
|
|
8020
|
+
let isSubmenuOpen = false;
|
|
7869
8021
|
return {
|
|
7870
8022
|
view: ({ attrs, children }) => {
|
|
7871
|
-
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;
|
|
7872
8024
|
if (divider) {
|
|
7873
8025
|
return m('li.divider');
|
|
7874
8026
|
}
|
|
7875
8027
|
if (subheader) {
|
|
7876
8028
|
return m('li.subheader', text || children);
|
|
7877
8029
|
}
|
|
7878
|
-
const
|
|
7879
|
-
const
|
|
7880
|
-
|
|
7881
|
-
|
|
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 }, [
|
|
7882
8073
|
m('a', {
|
|
7883
8074
|
href,
|
|
7884
|
-
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,
|
|
7885
8084
|
}, content),
|
|
7886
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
|
+
];
|
|
7887
8093
|
}
|
|
7888
|
-
return
|
|
7889
|
-
m('a', {
|
|
7890
|
-
onclick: disabled ? undefined : onclick,
|
|
7891
|
-
href: '#!',
|
|
7892
|
-
}, content),
|
|
7893
|
-
]);
|
|
8094
|
+
return mainItem;
|
|
7894
8095
|
},
|
|
7895
8096
|
};
|
|
7896
8097
|
};
|