mithril-materialized 3.2.2 → 3.3.1

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
@@ -2853,20 +2853,40 @@ const TextArea = () => {
2853
2853
  state.height = undefined;
2854
2854
  }
2855
2855
  };
2856
- const isControlled = (attrs) => attrs.value !== undefined && attrs.oninput !== undefined;
2856
+ const isControlled = (attrs) => attrs.value !== undefined && (attrs.oninput !== undefined || attrs.onchange !== undefined);
2857
2857
  return {
2858
2858
  oninit: ({ attrs }) => {
2859
+ const controlled = isControlled(attrs);
2860
+ const isNonInteractive = attrs.readonly || attrs.disabled;
2861
+ // Warn developer for improper controlled usage
2862
+ if (attrs.value !== undefined && !controlled && !isNonInteractive) {
2863
+ console.warn(`TextArea received 'value' prop without 'oninput' or 'onchange' handler. ` +
2864
+ `Use 'defaultValue' for uncontrolled components or add an event handler for controlled components.`);
2865
+ }
2859
2866
  // Initialize internal value for uncontrolled mode
2860
- if (!isControlled(attrs)) {
2867
+ if (!controlled) {
2861
2868
  state.internalValue = attrs.defaultValue || '';
2862
2869
  }
2863
2870
  },
2864
2871
  onremove: () => {
2865
2872
  },
2866
2873
  view: ({ attrs }) => {
2874
+ var _a, _b, _c, _d;
2867
2875
  const { className = 'col s12', helperText, iconName, id = state.id, value, placeholder, isMandatory, label, maxLength, oninput, onchange, onkeydown, onkeypress, onkeyup, onblur, style } = attrs, params = __rest(attrs, ["className", "helperText", "iconName", "id", "value", "placeholder", "isMandatory", "label", "maxLength", "oninput", "onchange", "onkeydown", "onkeypress", "onkeyup", "onblur", "style"]);
2868
2876
  const controlled = isControlled(attrs);
2869
- const currentValue = controlled ? value || '' : state.internalValue;
2877
+ const isNonInteractive = attrs.readonly || attrs.disabled;
2878
+ let currentValue;
2879
+ if (controlled) {
2880
+ currentValue = value || '';
2881
+ }
2882
+ else if (isNonInteractive) {
2883
+ // Non-interactive components: prefer defaultValue, fallback to value
2884
+ currentValue = (_b = (_a = attrs.defaultValue) !== null && _a !== void 0 ? _a : value) !== null && _b !== void 0 ? _b : '';
2885
+ }
2886
+ else {
2887
+ // Interactive uncontrolled: use internal state
2888
+ currentValue = (_d = (_c = state.internalValue) !== null && _c !== void 0 ? _c : attrs.defaultValue) !== null && _d !== void 0 ? _d : '';
2889
+ }
2870
2890
  return [
2871
2891
  // Hidden div for height measurement - positioned outside the input-field
2872
2892
  m('.hiddendiv', {
@@ -2997,7 +3017,8 @@ const InputField = (type, defaultClass = '') => () => {
2997
3017
  isDragging: false,
2998
3018
  activeThumb: null,
2999
3019
  };
3000
- const isControlled = (attrs) => 'value' in attrs && typeof attrs.value !== 'undefined' && typeof attrs.oninput === 'function';
3020
+ const isControlled = (attrs) => 'value' in attrs && typeof attrs.value !== 'undefined' &&
3021
+ (typeof attrs.oninput === 'function' || typeof attrs.onchange === 'function');
3001
3022
  const getValue = (target) => {
3002
3023
  const val = target.value;
3003
3024
  return (val ? (type === 'number' || type === 'range' ? +val : val) : val);
@@ -3043,8 +3064,15 @@ const InputField = (type, defaultClass = '') => () => {
3043
3064
  // Range slider rendering functions are now in separate module
3044
3065
  return {
3045
3066
  oninit: ({ attrs }) => {
3067
+ const controlled = isControlled(attrs);
3068
+ const isNonInteractive = attrs.readonly || attrs.disabled;
3069
+ // Warn developer for improper controlled usage
3070
+ if (attrs.value !== undefined && !controlled && !isNonInteractive) {
3071
+ console.warn(`${type} input received 'value' prop without 'oninput' or 'onchange' handler. ` +
3072
+ `Use 'defaultValue' for uncontrolled components or add an event handler for controlled components.`);
3073
+ }
3046
3074
  // Initialize internal value if not in controlled mode
3047
- if (!isControlled(attrs)) {
3075
+ if (!controlled) {
3048
3076
  const isNumeric = ['number', 'range'].includes(type);
3049
3077
  if (attrs.defaultValue !== undefined) {
3050
3078
  if (isNumeric) {
@@ -3060,7 +3088,7 @@ const InputField = (type, defaultClass = '') => () => {
3060
3088
  }
3061
3089
  },
3062
3090
  view: ({ attrs }) => {
3063
- var _a, _b;
3091
+ var _a, _b, _c, _d, _e, _f;
3064
3092
  const { className = 'col s12', dataError, dataSuccess, helperText, iconName, id = state.id, placeholder, isMandatory, label, maxLength, newRow, oninput, onchange, onkeydown, onkeypress, onkeyup, style, validate, canClear } = attrs, params = __rest(attrs, ["className", "dataError", "dataSuccess", "helperText", "iconName", "id", "placeholder", "isMandatory", "label", "maxLength", "newRow", "oninput", "onchange", "onkeydown", "onkeypress", "onkeyup", "style", "validate", "canClear"]);
3065
3093
  // const attributes = toAttrs(params);
3066
3094
  const cn = [newRow ? 'clear' : '', defaultClass, className].filter(Boolean).join(' ').trim() || undefined;
@@ -3080,7 +3108,19 @@ const InputField = (type, defaultClass = '') => () => {
3080
3108
  }
3081
3109
  const isNumeric = ['number', 'range'].includes(type);
3082
3110
  const controlled = isControlled(attrs);
3083
- const value = (controlled ? attrs.value : state.internalValue);
3111
+ const isNonInteractive = attrs.readonly || attrs.disabled;
3112
+ let value;
3113
+ if (controlled) {
3114
+ value = attrs.value;
3115
+ }
3116
+ else if (isNonInteractive) {
3117
+ // Non-interactive components: prefer defaultValue, fallback to value
3118
+ value = ((_c = (_b = attrs.defaultValue) !== null && _b !== void 0 ? _b : attrs.value) !== null && _c !== void 0 ? _c : (isNumeric ? 0 : ''));
3119
+ }
3120
+ else {
3121
+ // Interactive uncontrolled: use internal state
3122
+ value = ((_e = (_d = state.internalValue) !== null && _d !== void 0 ? _d : attrs.defaultValue) !== null && _e !== void 0 ? _e : (isNumeric ? 0 : ''));
3123
+ }
3084
3124
  const rangeType = type === 'range' && !attrs.minmax;
3085
3125
  return m('.input-field', { className: cn, style }, [
3086
3126
  iconName ? m('i.material-icons.prefix', iconName) : undefined,
@@ -3246,7 +3286,7 @@ const InputField = (type, defaultClass = '') => () => {
3246
3286
  }
3247
3287
  } })),
3248
3288
  // Clear button - only for text inputs with canClear enabled and has content
3249
- canClear && type === 'text' && ((_b = state.inputElement) === null || _b === void 0 ? void 0 : _b.value)
3289
+ canClear && type === 'text' && ((_f = state.inputElement) === null || _f === void 0 ? void 0 : _f.value)
3250
3290
  ? m(MaterialIcon, {
3251
3291
  name: 'close',
3252
3292
  className: 'input-clear-btn',
@@ -5643,17 +5683,35 @@ const RadioButtons = () => {
5643
5683
  return {
5644
5684
  oninit: ({ attrs }) => {
5645
5685
  state.componentId = attrs.id || uniqueId();
5686
+ const controlled = isControlled(attrs);
5687
+ // Warn developer for improper controlled usage
5688
+ if (attrs.checkedId !== undefined && !controlled && !attrs.disabled) {
5689
+ console.warn(`RadioButtons component received 'checkedId' prop without 'onchange' handler. ` +
5690
+ `Use 'defaultCheckedId' for uncontrolled components or add 'onchange' for controlled components.`);
5691
+ }
5646
5692
  // Initialize internal state for uncontrolled mode
5647
- if (!isControlled(attrs)) {
5693
+ if (!controlled) {
5648
5694
  state.internalCheckedId = attrs.defaultCheckedId;
5649
5695
  }
5650
5696
  },
5651
5697
  view: ({ attrs }) => {
5698
+ var _a, _b;
5652
5699
  const { checkedId, newRow, className = 'col s12', label = '', disabled, description, options, isMandatory, checkboxClass, layout = 'vertical', onchange, } = attrs;
5653
5700
  const { groupId, componentId } = state;
5654
5701
  const controlled = isControlled(attrs);
5655
5702
  // Get current checked ID from props or internal state
5656
- const currentCheckedId = controlled ? checkedId : state.internalCheckedId;
5703
+ let currentCheckedId;
5704
+ if (controlled) {
5705
+ currentCheckedId = checkedId;
5706
+ }
5707
+ else if (disabled) {
5708
+ // Non-interactive components: prefer defaultCheckedId, fallback to checkedId
5709
+ currentCheckedId = (_a = attrs.defaultCheckedId) !== null && _a !== void 0 ? _a : checkedId;
5710
+ }
5711
+ else {
5712
+ // Interactive uncontrolled: use internal state
5713
+ currentCheckedId = (_b = state.internalCheckedId) !== null && _b !== void 0 ? _b : attrs.defaultCheckedId;
5714
+ }
5657
5715
  const handleChange = (id) => {
5658
5716
  // Update internal state for uncontrolled mode
5659
5717
  if (!controlled) {
@@ -5783,8 +5841,14 @@ const Select = () => {
5783
5841
  return {
5784
5842
  oninit: ({ attrs }) => {
5785
5843
  state.id = attrs.id || uniqueId();
5844
+ const controlled = isControlled(attrs);
5845
+ // Warn developer for improper controlled usage
5846
+ if (attrs.checkedId !== undefined && !controlled && !attrs.disabled) {
5847
+ console.warn(`Select component received 'checkedId' prop without 'onchange' handler. ` +
5848
+ `Use 'defaultCheckedId' for uncontrolled components or add 'onchange' for controlled components.`);
5849
+ }
5786
5850
  // Initialize internal state for uncontrolled mode
5787
- if (!isControlled(attrs)) {
5851
+ if (!controlled) {
5788
5852
  const defaultIds = attrs.defaultCheckedId !== undefined
5789
5853
  ? Array.isArray(attrs.defaultCheckedId)
5790
5854
  ? attrs.defaultCheckedId
@@ -5800,16 +5864,32 @@ const Select = () => {
5800
5864
  document.removeEventListener('click', closeDropdown);
5801
5865
  },
5802
5866
  view: ({ attrs }) => {
5867
+ var _a;
5803
5868
  const controlled = isControlled(attrs);
5869
+ const { disabled } = attrs;
5804
5870
  // Get selected IDs from props or internal state
5805
- const selectedIds = controlled
5806
- ? attrs.checkedId !== undefined
5871
+ let selectedIds;
5872
+ if (controlled) {
5873
+ selectedIds = attrs.checkedId !== undefined
5807
5874
  ? Array.isArray(attrs.checkedId)
5808
5875
  ? attrs.checkedId
5809
5876
  : [attrs.checkedId]
5810
- : []
5811
- : state.internalSelectedIds;
5812
- const { newRow, className = 'col s12', key, options, multiple = false, label, helperText, placeholder = '', isMandatory, iconName, disabled, style, } = attrs;
5877
+ : [];
5878
+ }
5879
+ else if (disabled) {
5880
+ // Non-interactive components: prefer defaultCheckedId, fallback to checkedId
5881
+ const fallbackId = (_a = attrs.defaultCheckedId) !== null && _a !== void 0 ? _a : attrs.checkedId;
5882
+ selectedIds = fallbackId !== undefined
5883
+ ? Array.isArray(fallbackId)
5884
+ ? fallbackId
5885
+ : [fallbackId]
5886
+ : [];
5887
+ }
5888
+ else {
5889
+ // Interactive uncontrolled: use internal state
5890
+ selectedIds = state.internalSelectedIds;
5891
+ }
5892
+ const { newRow, className = 'col s12', key, options, multiple = false, label, helperText, placeholder = '', isMandatory, iconName, style, } = attrs;
5813
5893
  const finalClassName = newRow ? `${className} clear` : className;
5814
5894
  const selectedOptions = options.filter((opt) => isSelected(opt.id, selectedIds));
5815
5895
  return m('.input-field.select-space', {
@@ -8546,6 +8626,269 @@ const ImageList = () => {
8546
8626
  };
8547
8627
  };
8548
8628
 
8629
+ /** Default star icons */
8630
+ const DEFAULT_ICONS = {
8631
+ filled: '★',
8632
+ empty: '☆',
8633
+ half: '☆', // We'll handle half-fill with CSS
8634
+ };
8635
+ /** Create a Rating component */
8636
+ const Rating = () => {
8637
+ const state = {
8638
+ id: uniqueId(),
8639
+ internalValue: 0,
8640
+ hoverValue: null,
8641
+ isHovering: false,
8642
+ isFocused: false,
8643
+ };
8644
+ const isControlled = (attrs) => typeof attrs.value !== 'undefined' && typeof attrs.onchange === 'function';
8645
+ const getCurrentValue = (attrs) => {
8646
+ var _a, _b, _c, _d;
8647
+ const controlled = isControlled(attrs);
8648
+ const isNonInteractive = attrs.readonly || attrs.disabled;
8649
+ if (controlled) {
8650
+ return attrs.value || 0;
8651
+ }
8652
+ // Non-interactive components: prefer defaultValue, fallback to value
8653
+ if (isNonInteractive) {
8654
+ return (_b = (_a = attrs.defaultValue) !== null && _a !== void 0 ? _a : attrs.value) !== null && _b !== void 0 ? _b : 0;
8655
+ }
8656
+ // Interactive uncontrolled: use internal state (user can change it)
8657
+ return (_d = (_c = state.internalValue) !== null && _c !== void 0 ? _c : attrs.defaultValue) !== null && _d !== void 0 ? _d : 0;
8658
+ };
8659
+ const getDisplayValue = (attrs) => state.isHovering && state.hoverValue !== null ? state.hoverValue : getCurrentValue(attrs);
8660
+ const getLabelText = (value, max, getLabelFn) => {
8661
+ if (getLabelFn) {
8662
+ return getLabelFn(value, max);
8663
+ }
8664
+ if (value === 0) {
8665
+ return `No rating`;
8666
+ }
8667
+ if (value === 1) {
8668
+ return `1 star out of ${max}`;
8669
+ }
8670
+ return `${value} stars out of ${max}`;
8671
+ };
8672
+ const getSizeClass = (size = 'medium') => {
8673
+ switch (size) {
8674
+ case 'small':
8675
+ return 'rating--small';
8676
+ case 'large':
8677
+ return 'rating--large';
8678
+ default:
8679
+ return 'rating--medium';
8680
+ }
8681
+ };
8682
+ const getDensityClass = (density = 'standard') => {
8683
+ switch (density) {
8684
+ case 'compact':
8685
+ return 'rating--compact';
8686
+ case 'comfortable':
8687
+ return 'rating--comfortable';
8688
+ default:
8689
+ return 'rating--standard';
8690
+ }
8691
+ };
8692
+ const handleItemClick = (attrs, clickValue) => {
8693
+ var _a;
8694
+ if (attrs.readonly || attrs.disabled)
8695
+ return;
8696
+ const currentValue = getCurrentValue(attrs);
8697
+ const newValue = attrs.clearable && currentValue === clickValue ? 0 : clickValue;
8698
+ if (!isControlled(attrs)) {
8699
+ state.internalValue = newValue;
8700
+ }
8701
+ (_a = attrs.onchange) === null || _a === void 0 ? void 0 : _a.call(attrs, newValue);
8702
+ };
8703
+ const handleItemHover = (attrs, hoverValue) => {
8704
+ var _a;
8705
+ if (attrs.readonly || attrs.disabled)
8706
+ return;
8707
+ state.hoverValue = hoverValue;
8708
+ state.isHovering = true;
8709
+ (_a = attrs.onmouseover) === null || _a === void 0 ? void 0 : _a.call(attrs, hoverValue);
8710
+ };
8711
+ const handleMouseLeave = (attrs) => {
8712
+ if (attrs.readonly || attrs.disabled)
8713
+ return;
8714
+ state.isHovering = false;
8715
+ state.hoverValue = null;
8716
+ };
8717
+ const handleKeyDown = (attrs, e) => {
8718
+ var _a;
8719
+ if (attrs.readonly || attrs.disabled)
8720
+ return;
8721
+ const max = attrs.max || 5;
8722
+ const step = attrs.step || 1;
8723
+ const currentValue = getCurrentValue(attrs);
8724
+ let newValue = currentValue;
8725
+ switch (e.key) {
8726
+ case 'ArrowRight':
8727
+ case 'ArrowUp':
8728
+ e.preventDefault();
8729
+ newValue = Math.min(max, currentValue + step);
8730
+ break;
8731
+ case 'ArrowLeft':
8732
+ case 'ArrowDown':
8733
+ e.preventDefault();
8734
+ newValue = Math.max(0, currentValue - step);
8735
+ break;
8736
+ case 'Home':
8737
+ e.preventDefault();
8738
+ newValue = attrs.clearable ? 0 : step;
8739
+ break;
8740
+ case 'End':
8741
+ e.preventDefault();
8742
+ newValue = max;
8743
+ break;
8744
+ case ' ':
8745
+ case 'Enter':
8746
+ e.preventDefault();
8747
+ // If focused and not hovering, increment by step
8748
+ if (!state.isHovering) {
8749
+ newValue = currentValue + step > max ? (attrs.clearable ? 0 : step) : currentValue + step;
8750
+ }
8751
+ break;
8752
+ case 'Escape':
8753
+ if (attrs.clearable) {
8754
+ e.preventDefault();
8755
+ newValue = 0;
8756
+ }
8757
+ break;
8758
+ default:
8759
+ return;
8760
+ }
8761
+ if (newValue !== currentValue) {
8762
+ if (!isControlled(attrs)) {
8763
+ state.internalValue = newValue;
8764
+ }
8765
+ (_a = attrs.onchange) === null || _a === void 0 ? void 0 : _a.call(attrs, newValue);
8766
+ }
8767
+ };
8768
+ const RatingItem = () => {
8769
+ return {
8770
+ view: ({ attrs }) => {
8771
+ const { index, displayValue, step, icons, allowHalfSteps, disabled, onclick, onmouseover } = attrs;
8772
+ const itemValue = (index + 1) * step;
8773
+ // Calculate fill state based on displayValue vs itemValue
8774
+ const diff = displayValue - itemValue;
8775
+ const fillState = diff >= 0 ? 'full' : allowHalfSteps && diff >= -step / 2 ? 'half' : 'empty';
8776
+ return m('.rating__item', {
8777
+ className: [
8778
+ fillState === 'full' ? 'rating__item--filled' : '',
8779
+ fillState === 'half' ? 'rating__item--half' : '',
8780
+ fillState !== 'empty' ? 'rating__item--active' : '',
8781
+ disabled ? 'rating__item--disabled' : '',
8782
+ ]
8783
+ .filter(Boolean)
8784
+ .join(' '),
8785
+ onclick,
8786
+ onmouseover,
8787
+ }, [
8788
+ // Empty icon (background)
8789
+ m('.rating__icon.rating__icon--empty', { 'aria-hidden': 'true' }, typeof icons.empty === 'string' ? icons.empty : m(icons.empty)),
8790
+ // Filled icon (foreground)
8791
+ m('.rating__icon.rating__icon--filled', {
8792
+ 'aria-hidden': 'true',
8793
+ style: {
8794
+ clipPath: fillState === 'half' ? 'inset(0 50% 0 0)' : undefined,
8795
+ },
8796
+ }, typeof icons.filled === 'string' ? icons.filled : m(icons.filled)),
8797
+ ]);
8798
+ },
8799
+ };
8800
+ };
8801
+ return {
8802
+ oninit: ({ attrs }) => {
8803
+ const controlled = isControlled(attrs);
8804
+ const isNonInteractive = attrs.readonly || attrs.disabled;
8805
+ // Warn developer for improper controlled usage
8806
+ if (attrs.value !== undefined && !controlled && !isNonInteractive) {
8807
+ console.warn(`Rating component received 'value' prop without 'onchange' handler. ` +
8808
+ `Use 'defaultValue' for uncontrolled components or add 'onchange' for controlled components.`);
8809
+ }
8810
+ if (!controlled) {
8811
+ state.internalValue = attrs.defaultValue || 0;
8812
+ }
8813
+ },
8814
+ view: ({ attrs }) => {
8815
+ const { max = 5, step = 1, size = 'medium', density = 'standard', className = '', style = {}, readonly: readonly = false, disabled = false, id = state.id, name } = attrs, ariaAttrs = __rest(attrs, ["max", "step", "size", "density", "className", "style", "readonly", "disabled", "id", "name"]);
8816
+ const currentValue = getCurrentValue(attrs);
8817
+ const displayValue = getDisplayValue(attrs);
8818
+ const itemCount = Math.ceil(max / step);
8819
+ return m('.rating', {
8820
+ className: [
8821
+ 'rating',
8822
+ getSizeClass(size),
8823
+ getDensityClass(density),
8824
+ readonly ? 'rating--read-only' : '',
8825
+ disabled ? 'rating--disabled' : '',
8826
+ state.isFocused ? 'rating--focused' : '',
8827
+ className,
8828
+ ]
8829
+ .filter(Boolean)
8830
+ .join(' '),
8831
+ style,
8832
+ id,
8833
+ role: readonly ? 'img' : 'slider',
8834
+ tabindex: readonly || disabled ? -1 : 0,
8835
+ 'aria-valuemin': 0,
8836
+ 'aria-valuemax': max,
8837
+ 'aria-valuenow': currentValue,
8838
+ 'aria-valuetext': getLabelText(currentValue, max, attrs.getLabelText),
8839
+ 'aria-label': ariaAttrs['aria-label'] ||
8840
+ attrs.ariaLabel ||
8841
+ `Rating: ${getLabelText(currentValue, max, attrs.getLabelText)}`,
8842
+ 'aria-labelledby': ariaAttrs['aria-labelledby'],
8843
+ 'aria-readonly': readonly,
8844
+ 'aria-disabled': disabled,
8845
+ onkeydown: (e) => handleKeyDown(attrs, e),
8846
+ onfocus: () => {
8847
+ state.isFocused = true;
8848
+ },
8849
+ onblur: () => {
8850
+ state.isFocused = false;
8851
+ handleMouseLeave(attrs);
8852
+ },
8853
+ onmouseleave: () => handleMouseLeave(attrs),
8854
+ }, [
8855
+ // Hidden input for form submission
8856
+ name &&
8857
+ m('input', {
8858
+ type: 'hidden',
8859
+ name,
8860
+ value: currentValue,
8861
+ }),
8862
+ // Rating items
8863
+ m('.rating__items', {
8864
+ className: 'rating__items',
8865
+ },
8866
+ // Array.from({ length: itemCount }, (_, i) => renderRatingItem(attrs, i))
8867
+ [...Array(itemCount)].map((_, i) => {
8868
+ const itemValue = (i + 1) * step;
8869
+ return m(RatingItem, {
8870
+ key: `rating-item-${i}`,
8871
+ index: i,
8872
+ displayValue: displayValue,
8873
+ step,
8874
+ icons: Object.assign(Object.assign({}, DEFAULT_ICONS), attrs.icon),
8875
+ allowHalfSteps: attrs.allowHalfSteps,
8876
+ disabled: attrs.disabled,
8877
+ onclick: () => handleItemClick(attrs, itemValue),
8878
+ onmouseover: () => handleItemHover(attrs, itemValue),
8879
+ });
8880
+ })),
8881
+ // Screen reader text
8882
+ m('.rating__sr-only', {
8883
+ className: 'rating__sr-only',
8884
+ 'aria-live': 'polite',
8885
+ 'aria-atomic': 'true',
8886
+ }, getLabelText(displayValue, max, attrs.getLabelText)),
8887
+ ]);
8888
+ },
8889
+ };
8890
+ };
8891
+
8549
8892
  /**
8550
8893
  * @fileoverview Core TypeScript utility types for mithril-materialized library
8551
8894
  * These types improve type safety and developer experience across all components
@@ -8614,6 +8957,7 @@ exports.PushpinComponent = PushpinComponent;
8614
8957
  exports.RadioButton = RadioButton;
8615
8958
  exports.RadioButtons = RadioButtons;
8616
8959
  exports.RangeInput = RangeInput;
8960
+ exports.Rating = Rating;
8617
8961
  exports.RoundIconButton = RoundIconButton;
8618
8962
  exports.SearchSelect = SearchSelect;
8619
8963
  exports.SecondaryContent = SecondaryContent;