mithril-materialized 3.5.3 → 3.5.4

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.js CHANGED
@@ -7812,6 +7812,66 @@ const FileUpload = () => {
7812
7812
  };
7813
7813
  };
7814
7814
 
7815
+ // List of MaterialIcon SVG icons that are available
7816
+ const materialIconSvgNames = [
7817
+ 'caret', 'close', 'chevron', 'chevron_left', 'chevron_right', 'menu',
7818
+ 'expand', 'collapse', 'check', 'radio_checked', 'radio_unchecked',
7819
+ 'light_mode', 'dark_mode'
7820
+ ];
7821
+ /**
7822
+ * Helper function to render icons based on IconDefinition type
7823
+ */
7824
+ const renderIcon = (icon, style) => {
7825
+ if (!icon)
7826
+ return null;
7827
+ if (typeof icon === 'string') {
7828
+ // Check if this is a MaterialIcon SVG name
7829
+ if (materialIconSvgNames.includes(icon)) {
7830
+ return m(MaterialIcon, { name: icon, style });
7831
+ }
7832
+ // Fall back to Material Icons font for other icon names
7833
+ return m('i.material-icons', { style }, icon);
7834
+ }
7835
+ if (icon.type === 'svg') {
7836
+ // Inline SVG
7837
+ return m.trust(icon.content);
7838
+ }
7839
+ if (icon.type === 'image') {
7840
+ // Image URL
7841
+ return m('img', {
7842
+ src: icon.content,
7843
+ style: Object.assign(Object.assign({}, style), { width: '24px', height: '24px', objectFit: 'contain' }),
7844
+ });
7845
+ }
7846
+ return null;
7847
+ };
7848
+ /**
7849
+ * Helper function to render a single sidenav item (for header/footer items)
7850
+ */
7851
+ const renderSidenavItem = (item, isExpanded, position) => {
7852
+ const { text, icon, onclick, href, className = '' } = item;
7853
+ const isRightAligned = position === 'right';
7854
+ const content = isRightAligned
7855
+ ? [
7856
+ isExpanded && m('span.sidenav-item-text', { style: { 'flex': '1', 'text-align': 'left', 'margin-right': '8px' } }, text),
7857
+ renderIcon(icon, { 'min-width': '24px', 'width': '24px' }),
7858
+ ]
7859
+ : [
7860
+ renderIcon(icon, { 'min-width': '24px', 'width': '24px' }),
7861
+ isExpanded && m('span.sidenav-item-text', { style: { 'margin-left': '8px', 'flex': '1' } }, text),
7862
+ ];
7863
+ const linkStyle = {
7864
+ display: 'flex',
7865
+ 'align-items': 'center',
7866
+ padding: isExpanded ? '12px 16px' : '12px 18px',
7867
+ 'justify-content': isExpanded ? (isRightAligned ? 'flex-end' : 'flex-start') : 'center',
7868
+ };
7869
+ return m('li', { class: className }, m('a', {
7870
+ href: href || '#!',
7871
+ onclick: onclick,
7872
+ style: linkStyle,
7873
+ }, content));
7874
+ };
7815
7875
  /**
7816
7876
  * Sidenav Component
7817
7877
  * A responsive navigation drawer that slides in from the side
@@ -7934,6 +7994,8 @@ const Sidenav = () => {
7934
7994
  name: 'menu',
7935
7995
  style: { width: '24px', height: '24px' },
7936
7996
  })),
7997
+ // Header item (if provided, appears before expand/collapse toggle)
7998
+ attrs.header && renderSidenavItem(attrs.header, isExpanded, position),
7937
7999
  // Expand/collapse toggle button (if expandable, right below hamburger)
7938
8000
  expandable &&
7939
8001
  m('li.sidenav-expand-toggle', {
@@ -7962,6 +8024,8 @@ const Sidenav = () => {
7962
8024
  return child;
7963
8025
  })
7964
8026
  : children,
8027
+ // Footer item (if provided, appears at the bottom)
8028
+ attrs.footer && renderSidenavItem(attrs.footer, isExpanded, position),
7965
8029
  ]),
7966
8030
  ];
7967
8031
  },
@@ -7980,43 +8044,42 @@ const NavbarSubItem = () => {
7980
8044
  }
7981
8045
  };
7982
8046
  const isRightAligned = position === 'right';
8047
+ // Render indicator icon for checkbox/radio modes
8048
+ const indicatorIcon = mode !== 'none'
8049
+ ? m(MaterialIcon, {
8050
+ name: mode === 'checkbox' ? (selected ? 'check' : 'close') : selected ? 'radio_checked' : 'radio_unchecked',
8051
+ style: {
8052
+ width: '18px',
8053
+ height: '18px',
8054
+ opacity: mode === 'checkbox' && !selected ? '0.3' : '1',
8055
+ },
8056
+ })
8057
+ : null;
7983
8058
  const submenuContent = isRightAligned
7984
8059
  ? [
7985
8060
  // Right-aligned: text on left, icons on right
7986
8061
  isExpanded && m('span', { style: { 'flex': '1', 'text-align': 'left' } }, text),
7987
- icon && isExpanded && m('i.material-icons', { style: { 'font-size': '18px' } }, icon),
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
- }),
8062
+ icon && isExpanded && renderIcon(icon, { 'font-size': '18px' }),
8063
+ indicatorIcon,
7996
8064
  ]
7997
8065
  : [
7998
8066
  // Left-aligned: indicator on left, text and icon on right
7999
- m(MaterialIcon, {
8000
- name: mode === 'checkbox' ? (selected ? 'check' : 'close') : selected ? 'radio_checked' : 'radio_unchecked',
8001
- style: {
8002
- width: '18px',
8003
- height: '18px',
8004
- opacity: mode === 'checkbox' && !selected ? '0.3' : '1',
8005
- },
8006
- }),
8007
- icon && isExpanded && m('i.material-icons', { style: { 'font-size': '18px', 'margin-left': '8px' } }, icon),
8008
- isExpanded && m('span', { style: { 'margin-left': icon ? '8px' : '8px' } }, text),
8067
+ indicatorIcon,
8068
+ icon && isExpanded && renderIcon(icon, { 'font-size': '18px', 'margin-left': indicatorIcon ? '8px' : '0' }),
8069
+ isExpanded && m('span', { style: { 'margin-left': icon || indicatorIcon ? '8px' : '0' } }, text),
8009
8070
  ];
8010
8071
  return m('li.sidenav-subitem', {
8011
8072
  class: selected ? 'selected' : '',
8012
8073
  style: {
8013
- padding: isExpanded ? '8px 16px 8px 48px' : '8px 16px',
8074
+ padding: isExpanded ? '0 16px 0 48px' : '0 16px',
8014
8075
  cursor: 'pointer',
8015
8076
  display: 'flex',
8016
8077
  'align-items': 'center',
8017
8078
  gap: '8px',
8018
8079
  'font-size': '0.9em',
8019
8080
  'justify-content': isRightAligned ? 'space-between' : 'flex-start',
8081
+ height: '48px',
8082
+ 'min-height': '48px',
8020
8083
  },
8021
8084
  onclick: handleClick,
8022
8085
  }, submenuContent);
@@ -8048,8 +8111,8 @@ const SidenavItem = () => {
8048
8111
  .filter(Boolean)
8049
8112
  .join(' ') || undefined;
8050
8113
  const handleMainClick = (e) => {
8051
- e.preventDefault();
8052
8114
  if (hasSubmenu) {
8115
+ e.preventDefault();
8053
8116
  isSubmenuOpen = active ? !isSubmenuOpen : true;
8054
8117
  }
8055
8118
  if (onclick && !disabled) {
@@ -8066,11 +8129,11 @@ const SidenavItem = () => {
8066
8129
  ? [
8067
8130
  // Right-aligned: text on left, icon on right
8068
8131
  isExpanded && m('span.sidenav-item-text', { style: { 'flex': '1', 'text-align': 'left', 'margin-right': '8px' } }, text || children),
8069
- m('i.material-icons', { style: { 'min-width': '24px', 'width': '24px' } }, icon || ''),
8132
+ renderIcon(icon, { 'min-width': '24px', 'width': '24px' }),
8070
8133
  ]
8071
8134
  : [
8072
8135
  // Left-aligned: icon on left, text on right
8073
- m('i.material-icons', { style: { 'min-width': '24px', 'width': '24px' } }, icon || ''),
8136
+ renderIcon(icon, { 'min-width': '24px', 'width': '24px' }),
8074
8137
  isExpanded && m('span.sidenav-item-text', { style: { 'margin-left': '8px', 'flex': '1' } }, text || children),
8075
8138
  ];
8076
8139
  const linkStyle = {