mithril-materialized 3.9.0 → 3.10.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.js CHANGED
@@ -507,6 +507,106 @@ const Autocomplete = () => {
507
507
  };
508
508
  };
509
509
 
510
+ /**
511
+ * Badge component
512
+ *
513
+ * Displays a badge anchored to a child element. Commonly used for notifications,
514
+ * counts, or status indicators. Supports flexible positioning, colors, and variants.
515
+ *
516
+ * @example
517
+ * ```typescript
518
+ * // Basic notification badge
519
+ * m(Badge, { badgeContent: 5 },
520
+ * m('button.btn', 'Messages')
521
+ * )
522
+ *
523
+ * // Dot badge on avatar
524
+ * m(Badge, {
525
+ * variant: 'dot',
526
+ * color: 'green',
527
+ * overlap: 'circular'
528
+ * },
529
+ * m('img.circle', { src: 'avatar.jpg' })
530
+ * )
531
+ * ```
532
+ */
533
+ const Badge = () => {
534
+ return {
535
+ view: ({ attrs, children }) => {
536
+ const { badgeContent, max, anchorOrigin = { vertical: 'top', horizontal: 'right' }, overlap = 'rectangular', variant = 'standard', color = 'red', colorIntensity, invisible = false, showZero = false, 'aria-label': ariaLabel, badgeClassName = '', className = '' } = attrs, params = __rest(attrs, ["badgeContent", "max", "anchorOrigin", "overlap", "variant", "color", "colorIntensity", "invisible", "showZero", 'aria-label', "badgeClassName", "className"]);
537
+ // === VALIDATION: Single child element ===
538
+ const childArray = Array.isArray(children) ? children : children ? [children] : [];
539
+ if (childArray.length === 0) {
540
+ console.warn('Badge component requires a child element');
541
+ return null;
542
+ }
543
+ if (childArray.length > 1) {
544
+ console.warn('Badge component should only wrap a single child element. Using first child only.');
545
+ }
546
+ const child = childArray[0];
547
+ // === VISIBILITY LOGIC ===
548
+ // Hide badge if:
549
+ // 1. invisible prop is true, OR
550
+ // 2. For standard variant: badgeContent is undefined/null OR (badgeContent is 0 AND !showZero)
551
+ const shouldHideBadge = invisible ||
552
+ (variant === 'standard' &&
553
+ (badgeContent === undefined ||
554
+ badgeContent === null ||
555
+ (badgeContent === 0 && !showZero)));
556
+ // === BADGE CONTENT FORMATTING ===
557
+ // Apply max capping: if badgeContent > max, show "max+"
558
+ const getDisplayContent = () => {
559
+ if (variant === 'dot')
560
+ return '';
561
+ if (typeof badgeContent === 'number' && max !== undefined && badgeContent > max) {
562
+ return `${max}+`;
563
+ }
564
+ return String(badgeContent !== null && badgeContent !== void 0 ? badgeContent : '');
565
+ };
566
+ const displayContent = getDisplayContent();
567
+ // === CSS CLASS ASSEMBLY ===
568
+ // Wrapper classes
569
+ const wrapperClasses = ['badge-wrapper', className].filter(Boolean).join(' ').trim() || undefined;
570
+ // Badge element classes - using m-badge prefix to avoid Materialize conflicts
571
+ const positionClass = `m-badge--${anchorOrigin.vertical}-${anchorOrigin.horizontal}`;
572
+ const badgeClasses = [
573
+ 'm-badge',
574
+ `m-badge--${variant}`,
575
+ positionClass,
576
+ `m-badge--${overlap}`,
577
+ `m-badge--${color}`,
578
+ colorIntensity ? `m-badge--${colorIntensity}` : '',
579
+ shouldHideBadge ? 'm-badge--invisible' : '',
580
+ badgeClassName,
581
+ ]
582
+ .filter(Boolean)
583
+ .join(' ')
584
+ .trim();
585
+ // === ARIA ATTRIBUTES ===
586
+ const badgeAriaLabel = ariaLabel ||
587
+ (variant === 'dot'
588
+ ? 'notification indicator'
589
+ : displayContent
590
+ ? `${displayContent} notifications`
591
+ : 'notification badge');
592
+ // === RENDER ===
593
+ return m('.badge-wrapper', Object.assign(Object.assign({}, params), { className: wrapperClasses }), [
594
+ // Child element
595
+ child,
596
+ // Badge element - only render if not hidden
597
+ !shouldHideBadge
598
+ ? m('span', {
599
+ className: badgeClasses,
600
+ 'aria-label': badgeAriaLabel,
601
+ role: 'status',
602
+ 'aria-live': 'polite',
603
+ }, variant === 'standard' ? displayContent : null)
604
+ : null,
605
+ ]);
606
+ },
607
+ };
608
+ };
609
+
510
610
  /**
511
611
  * A simple material icon, defined by its icon name.
512
612
  *
@@ -11033,6 +11133,7 @@ const isValidationError = (result) => !isValidationSuccess(result);
11033
11133
  exports.AnalogClock = AnalogClock;
11034
11134
  exports.AnchorItem = AnchorItem;
11035
11135
  exports.Autocomplete = Autocomplete;
11136
+ exports.Badge = Badge;
11036
11137
  exports.Breadcrumb = Breadcrumb;
11037
11138
  exports.BreadcrumbManager = BreadcrumbManager;
11038
11139
  exports.Button = Button;