mtrl 0.2.7 → 0.2.9

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.
Files changed (190) hide show
  1. package/index.ts +2 -0
  2. package/package.json +14 -3
  3. package/src/components/badge/api.ts +23 -14
  4. package/src/components/badge/badge.ts +2 -2
  5. package/src/components/badge/config.ts +10 -11
  6. package/src/components/badge/features.ts +15 -10
  7. package/src/components/badge/index.ts +27 -2
  8. package/src/components/badge/types.ts +28 -8
  9. package/src/components/bottom-app-bar/bottom-app-bar.ts +2 -44
  10. package/src/components/bottom-app-bar/config.ts +1 -45
  11. package/src/components/bottom-app-bar/index.ts +7 -1
  12. package/src/components/bottom-app-bar/types.ts +7 -1
  13. package/src/components/button/button.ts +0 -1
  14. package/src/components/button/config.ts +1 -2
  15. package/src/components/button/index.ts +10 -2
  16. package/src/components/button/types.ts +14 -2
  17. package/src/components/card/config.ts +17 -9
  18. package/src/components/card/content.ts +8 -10
  19. package/src/components/card/features.ts +4 -6
  20. package/src/components/card/index.ts +29 -2
  21. package/src/components/card/types.ts +6 -23
  22. package/src/components/checkbox/config.ts +3 -4
  23. package/src/components/checkbox/index.ts +1 -2
  24. package/src/components/checkbox/types.ts +12 -3
  25. package/src/components/chip/api.ts +170 -221
  26. package/src/components/chip/chip.ts +34 -302
  27. package/src/components/chip/config.ts +1 -2
  28. package/src/components/chip/index.ts +10 -2
  29. package/src/components/chip/types.ts +224 -35
  30. package/src/components/datepicker/api.ts +18 -25
  31. package/src/components/datepicker/config.ts +9 -12
  32. package/src/components/datepicker/datepicker.ts +7 -12
  33. package/src/components/datepicker/index.ts +10 -7
  34. package/src/components/datepicker/render.ts +16 -18
  35. package/src/components/datepicker/types.ts +164 -35
  36. package/src/components/datepicker/utils.ts +1 -2
  37. package/src/components/dialog/api.ts +7 -8
  38. package/src/components/dialog/config.ts +3 -4
  39. package/src/components/dialog/features.ts +56 -22
  40. package/src/components/dialog/index.ts +38 -8
  41. package/src/components/dialog/types.ts +33 -10
  42. package/src/components/divider/index.ts +5 -1
  43. package/src/components/extended-fab/config.ts +6 -2
  44. package/src/components/extended-fab/index.ts +7 -2
  45. package/src/components/extended-fab/types.ts +21 -4
  46. package/src/components/fab/config.ts +3 -4
  47. package/src/components/fab/fab.ts +1 -1
  48. package/src/components/fab/index.ts +7 -2
  49. package/src/components/fab/types.ts +21 -4
  50. package/src/components/list/config.ts +4 -5
  51. package/src/components/list/features.ts +6 -7
  52. package/src/components/list/index.ts +7 -9
  53. package/src/components/list/list-item.ts +12 -13
  54. package/src/components/list/types.ts +50 -5
  55. package/src/components/list/utils.ts +30 -3
  56. package/src/components/menu/features/items-manager.ts +9 -9
  57. package/src/components/menu/features/positioning.ts +7 -7
  58. package/src/components/menu/features/visibility.ts +7 -7
  59. package/src/components/menu/index.ts +7 -9
  60. package/src/components/menu/menu-item.ts +6 -6
  61. package/src/components/menu/menu.ts +22 -0
  62. package/src/components/menu/types.ts +29 -10
  63. package/src/components/menu/utils.ts +67 -0
  64. package/src/components/navigation/api.ts +131 -96
  65. package/src/components/navigation/config.ts +22 -10
  66. package/src/components/navigation/features/controller.ts +273 -0
  67. package/src/components/navigation/features/items.ts +160 -87
  68. package/src/components/navigation/index.ts +0 -6
  69. package/src/components/navigation/nav-item.ts +12 -24
  70. package/src/components/navigation/navigation.ts +21 -8
  71. package/src/components/navigation/system-types.ts +124 -0
  72. package/src/components/navigation/system.ts +776 -0
  73. package/src/components/navigation/types.ts +228 -203
  74. package/src/components/progress/api.ts +2 -3
  75. package/src/components/progress/config.ts +2 -3
  76. package/src/components/progress/index.ts +0 -1
  77. package/src/components/progress/progress.ts +1 -2
  78. package/src/components/progress/types.ts +186 -33
  79. package/src/components/radios/config.ts +1 -1
  80. package/src/components/radios/index.ts +0 -1
  81. package/src/components/radios/types.ts +0 -7
  82. package/src/components/search/config.ts +1 -2
  83. package/src/components/search/features/search.ts +14 -15
  84. package/src/components/search/features/states.ts +5 -1
  85. package/src/components/search/features/structure.ts +3 -4
  86. package/src/components/search/index.ts +0 -3
  87. package/src/components/search/types.ts +18 -6
  88. package/src/components/segmented-button/config.ts +20 -7
  89. package/src/components/segmented-button/segment.ts +6 -7
  90. package/src/components/segmented-button/segmented-button.ts +4 -5
  91. package/src/components/segmented-button/types.ts +37 -2
  92. package/src/components/slider/config.ts +20 -2
  93. package/src/components/slider/features/controller.ts +761 -0
  94. package/src/components/slider/features/handlers.ts +18 -15
  95. package/src/components/slider/features/index.ts +3 -2
  96. package/src/components/slider/features/range.ts +104 -0
  97. package/src/components/slider/slider.ts +34 -14
  98. package/src/components/slider/structure.ts +152 -0
  99. package/src/components/slider/types.ts +34 -8
  100. package/src/components/snackbar/config.ts +2 -3
  101. package/src/components/snackbar/constants.ts +0 -32
  102. package/src/components/snackbar/index.ts +0 -1
  103. package/src/components/snackbar/position.ts +9 -1
  104. package/src/components/snackbar/types.ts +122 -46
  105. package/src/components/switch/config.ts +2 -3
  106. package/src/components/switch/index.ts +0 -1
  107. package/src/components/switch/types.ts +3 -2
  108. package/src/components/tabs/config.ts +3 -4
  109. package/src/components/tabs/index.ts +0 -15
  110. package/src/components/tabs/tab-api.ts +12 -4
  111. package/src/components/tabs/tab.ts +18 -6
  112. package/src/components/tabs/types.ts +13 -3
  113. package/src/components/textfield/api.ts +53 -0
  114. package/src/components/textfield/config.ts +2 -3
  115. package/src/components/textfield/features.ts +322 -0
  116. package/src/components/textfield/index.ts +0 -1
  117. package/src/components/textfield/textfield.ts +8 -0
  118. package/src/components/textfield/types.ts +29 -6
  119. package/src/components/timepicker/api.ts +1 -1
  120. package/src/components/timepicker/clockdial.ts +2 -5
  121. package/src/components/timepicker/config.ts +102 -4
  122. package/src/components/timepicker/index.ts +1 -6
  123. package/src/components/timepicker/render.ts +1 -1
  124. package/src/components/timepicker/timepicker.ts +1 -1
  125. package/src/components/tooltip/api.ts +1 -1
  126. package/src/components/tooltip/config.ts +27 -6
  127. package/src/components/tooltip/index.ts +0 -1
  128. package/src/components/tooltip/types.ts +13 -3
  129. package/src/core/compose/features/textinput.ts +15 -2
  130. package/src/core/compose/features/textlabel.ts +0 -3
  131. package/src/core/composition/features/dom.ts +33 -0
  132. package/src/core/composition/features/icon.ts +131 -0
  133. package/src/core/composition/features/index.ts +11 -0
  134. package/src/core/composition/features/label.ts +156 -0
  135. package/src/core/composition/features/structure.ts +22 -0
  136. package/src/core/composition/index.ts +26 -0
  137. package/src/core/index.ts +1 -1
  138. package/src/core/structure.ts +288 -0
  139. package/src/index.ts +1 -0
  140. package/src/styles/components/_navigation-mobile.scss +244 -0
  141. package/src/styles/components/_navigation-system.scss +151 -0
  142. package/src/{components/tabs/_styles.scss → styles/components/_tabs.scss} +1 -1
  143. package/src/{components/textfield/_styles.scss → styles/components/_textfield.scss} +314 -72
  144. package/src/styles/main.scss +98 -49
  145. package/src/components/badge/constants.ts +0 -40
  146. package/src/components/button/constants.ts +0 -11
  147. package/src/components/card/constants.ts +0 -84
  148. package/src/components/datepicker/constants.ts +0 -98
  149. package/src/components/dialog/constants.ts +0 -32
  150. package/src/components/extended-fab/constants.ts +0 -36
  151. package/src/components/fab/constants.ts +0 -41
  152. package/src/components/menu/constants.ts +0 -154
  153. package/src/components/navigation/constants.ts +0 -200
  154. package/src/components/progress/constants.ts +0 -29
  155. package/src/components/search/constants.ts +0 -21
  156. package/src/components/segmented-button/constants.ts +0 -42
  157. package/src/components/slider/features/slider.ts +0 -318
  158. package/src/components/slider/features/structure.ts +0 -181
  159. package/src/components/slider/features/ui.ts +0 -388
  160. package/src/components/switch/constants.ts +0 -80
  161. package/src/components/tabs/constants.ts +0 -89
  162. package/src/components/textfield/constants.ts +0 -100
  163. package/src/components/timepicker/constants.ts +0 -138
  164. /package/src/{components/badge/_styles.scss → styles/components/_badge.scss} +0 -0
  165. /package/src/{components/bottom-app-bar/_styles.scss → styles/components/_bottom-app-bar.scss} +0 -0
  166. /package/src/{components/button/_styles.scss → styles/components/_button.scss} +0 -0
  167. /package/src/{components/card/_styles.scss → styles/components/_card.scss} +0 -0
  168. /package/src/{components/carousel/_styles.scss → styles/components/_carousel.scss} +0 -0
  169. /package/src/{components/checkbox/_styles.scss → styles/components/_checkbox.scss} +0 -0
  170. /package/src/{components/chip/_styles.scss → styles/components/_chip.scss} +0 -0
  171. /package/src/{components/datepicker/_styles.scss → styles/components/_datepicker.scss} +0 -0
  172. /package/src/{components/dialog/_styles.scss → styles/components/_dialog.scss} +0 -0
  173. /package/src/{components/divider/_styles.scss → styles/components/_divider.scss} +0 -0
  174. /package/src/{components/extended-fab/_styles.scss → styles/components/_extended-fab.scss} +0 -0
  175. /package/src/{components/fab/_styles.scss → styles/components/_fab.scss} +0 -0
  176. /package/src/{components/list/_styles.scss → styles/components/_list.scss} +0 -0
  177. /package/src/{components/menu/_styles.scss → styles/components/_menu.scss} +0 -0
  178. /package/src/{components/navigation/_styles.scss → styles/components/_navigation.scss} +0 -0
  179. /package/src/{components/progress/_styles.scss → styles/components/_progress.scss} +0 -0
  180. /package/src/{components/radios/_styles.scss → styles/components/_radios.scss} +0 -0
  181. /package/src/{components/search/_styles.scss → styles/components/_search.scss} +0 -0
  182. /package/src/{components/segmented-button/_styles.scss → styles/components/_segmented-button.scss} +0 -0
  183. /package/src/{components/sheet/_styles.scss → styles/components/_sheet.scss} +0 -0
  184. /package/src/{components/slider/_styles.scss → styles/components/_slider.scss} +0 -0
  185. /package/src/{components/snackbar/_styles.scss → styles/components/_snackbar.scss} +0 -0
  186. /package/src/{components/switch/_styles.scss → styles/components/_switch.scss} +0 -0
  187. /package/src/{components/timepicker/_styles.scss → styles/components/_timepicker.scss} +0 -0
  188. /package/src/{components/tooltip/_styles.scss → styles/components/_tooltip.scss} +0 -0
  189. /package/src/{components/top-app-bar/_styles.scss → styles/components/_top-app-bar.scss} +0 -0
  190. /package/src/styles/utilities/{_color.scss → _colors.scss} +0 -0
@@ -2,8 +2,11 @@
2
2
  import { PREFIX } from '../../core/config';
3
3
  import { pipe } from '../../core/compose';
4
4
  import { createBase, withElement } from '../../core/compose/component';
5
- import { CardContentConfig } from './types';
6
- import { CARD_CONTENT_PADDING } from './constants';
5
+ import { createElement } from '../../core/dom/create';
6
+ import { CardContentConfig, CardHeaderConfig, CardMediaConfig, CardActionsConfig } from './types';
7
+
8
+ // Constants for content padding
9
+ export const CARD_CONTENT_PADDING = true;
7
10
 
8
11
  /**
9
12
  * Creates a card content component
@@ -78,9 +81,6 @@ export const createCardContent = (config: CardContentConfig = {}): HTMLElement =
78
81
  }
79
82
  };
80
83
 
81
- // src/components/card/header.ts
82
- import { createElement } from '../../core/dom/create';
83
-
84
84
  /**
85
85
  * Creates a card header component
86
86
  *
@@ -103,7 +103,7 @@ import { createElement } from '../../core/dom/create';
103
103
  * });
104
104
  * ```
105
105
  */
106
- export const createCardHeader = (config: any = {}): HTMLElement => {
106
+ export const createCardHeader = (config: CardHeaderConfig = {}): HTMLElement => {
107
107
  const baseConfig = {
108
108
  ...config,
109
109
  componentName: 'card-header',
@@ -200,7 +200,6 @@ export const createCardHeader = (config: any = {}): HTMLElement => {
200
200
  }
201
201
  };
202
202
 
203
- // src/components/card/actions.ts
204
203
  /**
205
204
  * Creates a card actions component
206
205
  *
@@ -225,7 +224,7 @@ export const createCardHeader = (config: any = {}): HTMLElement => {
225
224
  * });
226
225
  * ```
227
226
  */
228
- export const createCardActions = (config: any = {}): HTMLElement => {
227
+ export const createCardActions = (config: CardActionsConfig = {}): HTMLElement => {
229
228
  const baseConfig = {
230
229
  ...config,
231
230
  componentName: 'card-actions',
@@ -273,7 +272,6 @@ export const createCardActions = (config: any = {}): HTMLElement => {
273
272
  }
274
273
  };
275
274
 
276
- // src/components/card/media.ts
277
275
  /**
278
276
  * Creates a card media component
279
277
  *
@@ -296,7 +294,7 @@ export const createCardActions = (config: any = {}): HTMLElement => {
296
294
  * });
297
295
  * ```
298
296
  */
299
- export const createCardMedia = (config: any = {}): HTMLElement => {
297
+ export const createCardMedia = (config: CardMediaConfig = {}): HTMLElement => {
300
298
  const baseConfig = {
301
299
  ...config,
302
300
  componentName: 'card-media',
@@ -2,9 +2,7 @@
2
2
  import { PREFIX } from '../../core/config';
3
3
  import { createElement } from '../../core/dom/create';
4
4
  import { BaseComponent, CardComponent, LoadingFeature, ExpandableFeature, SwipeableFeature } from './types';
5
-
6
- import { createCardHeader, createCardContent, createCardMedia, createCardActions } from './content';
7
- import { BaseComponent, CardComponent, CardHeaderConfig, CardContentConfig, CardMediaConfig, CardActionsConfig, CardSchema, ButtonConfig } from './types';
5
+ import { CARD_ELEVATION_LEVELS } from './config';
8
6
 
9
7
  interface LoadingConfig {
10
8
  initialState?: boolean;
@@ -115,9 +113,9 @@ export const withElevation = (component: BaseComponent): BaseComponent => {
115
113
 
116
114
  // Set initial elevation based on variant
117
115
  if (config.variant === 'elevated') {
118
- component.element.style.setProperty('--card-elevation', '1');
116
+ component.element.style.setProperty('--card-elevation', String(CARD_ELEVATION_LEVELS.LEVEL1));
119
117
  } else {
120
- component.element.style.setProperty('--card-elevation', '0');
118
+ component.element.style.setProperty('--card-elevation', String(CARD_ELEVATION_LEVELS.LEVEL0));
121
119
  }
122
120
 
123
121
  return component;
@@ -266,7 +264,7 @@ export const withExpandable = (config: ExpandableConfig = {}) => (component: Bas
266
264
  * onSwipeLeft: (card) => console.log('Swiped left'),
267
265
  * onSwipeRight: (card) => console.log('Swiped right')
268
266
  * })
269
- * )({ variant: CardVariant.ELEVATED });
267
+ * )({ variant: 'elevated' });
270
268
  * ```
271
269
  */
272
270
  export const withSwipeable = (config: SwipeableConfig = {}) => (component: BaseComponent): BaseComponent & { swipeable: SwipeableFeature } => {
@@ -29,7 +29,7 @@ export {
29
29
 
30
30
  export {
31
31
  CardVariant,
32
- CardElevation,
32
+ CardElevationLevel,
33
33
  CardSchema,
34
34
  CardHeaderConfig,
35
35
  CardContentConfig,
@@ -38,4 +38,31 @@ export {
38
38
  CardAriaAttributes,
39
39
  CardComponent
40
40
  } from './types';
41
- export { CARD_VARIANTS, CARD_ELEVATIONS, CARD_WIDTHS, CARD_CORNER_RADIUS } from './constants';
41
+
42
+ // Export card constants for backward compatibility
43
+ export const CARD_VARIANTS = {
44
+ ELEVATED: 'elevated',
45
+ FILLED: 'filled',
46
+ OUTLINED: 'outlined'
47
+ } as const;
48
+
49
+ export const CARD_ELEVATIONS = {
50
+ LEVEL0: 0,
51
+ LEVEL1: 1,
52
+ LEVEL2: 2,
53
+ LEVEL4: 4
54
+ } as const;
55
+
56
+ // Additional constants
57
+ export const CARD_WIDTHS = {
58
+ SMALL: '344px',
59
+ MEDIUM: '480px',
60
+ LARGE: '624px',
61
+ FULL: '100%'
62
+ } as const;
63
+
64
+ export const CARD_CORNER_RADIUS = {
65
+ SMALL: '8px',
66
+ MEDIUM: '12px',
67
+ LARGE: '16px'
68
+ } as const;
@@ -1,31 +1,14 @@
1
1
  // src/components/card/types.ts
2
+
2
3
  /**
3
- * Card variant types following Material Design 3 specifications
4
- * @enum {string}
4
+ * Card variant types
5
5
  */
6
- export enum CardVariant {
7
- /** Elevated card with shadow */
8
- ELEVATED = 'elevated',
9
- /** Filled card with higher surface container color */
10
- FILLED = 'filled',
11
- /** Outlined card with border */
12
- OUTLINED = 'outlined'
13
- }
6
+ export type CardVariant = 'elevated' | 'filled' | 'outlined';
14
7
 
15
8
  /**
16
- * Card elevation levels based on MD3 guidelines
17
- * @enum {number}
9
+ * Card elevation levels
18
10
  */
19
- export enum CardElevation {
20
- /** No elevation (for filled and outlined variants) */
21
- LEVEL0 = 0,
22
- /** Default elevation for elevated cards */
23
- LEVEL1 = 1,
24
- /** Elevation for hovered state */
25
- LEVEL2 = 2,
26
- /** Elevation for dragged state */
27
- LEVEL4 = 4
28
- }
11
+ export type CardElevationLevel = 0 | 1 | 2 | 4;
29
12
 
30
13
  /**
31
14
  * Button configuration interface for buttons shorthand
@@ -48,7 +31,7 @@ export interface ButtonConfig {
48
31
  */
49
32
  export interface CardSchema {
50
33
  /** Card variant type (elevated, filled, outlined) */
51
- variant?: CardVariant;
34
+ variant?: CardVariant | string;
52
35
  /** Whether the card is interactive */
53
36
  interactive?: boolean;
54
37
  /** Whether the card should take full width */
@@ -5,14 +5,13 @@ import {
5
5
  BaseComponentConfig
6
6
  } from '../../core/config/component-config';
7
7
  import { CheckboxConfig, BaseComponent, ApiOptions } from './types';
8
- import { CHECKBOX_VARIANTS, CHECKBOX_LABEL_POSITION } from './constants';
9
8
 
10
9
  /**
11
10
  * Default configuration for the Checkbox component
12
11
  */
13
12
  export const defaultConfig: CheckboxConfig = {
14
- variant: CHECKBOX_VARIANTS.FILLED,
15
- labelPosition: CHECKBOX_LABEL_POSITION.END
13
+ variant: 'filled',
14
+ labelPosition: 'end'
16
15
  };
17
16
 
18
17
  /**
@@ -58,7 +57,7 @@ export const withCheckIcon = (config: CheckboxConfig) => (component: BaseCompone
58
57
  * @param {CheckboxConfig} config - Component configuration
59
58
  */
60
59
  export const withLabelPosition = (config: CheckboxConfig) => (component: BaseComponent): BaseComponent => {
61
- const position = config.labelPosition || CHECKBOX_LABEL_POSITION.END;
60
+ const position = config.labelPosition || 'end';
62
61
  const positionClass = `${config.prefix}-checkbox--label-${position}`;
63
62
 
64
63
  component.element.classList.add(positionClass);
@@ -1,4 +1,3 @@
1
1
  // src/components/checkbox/index.ts
2
2
  export { default } from './checkbox';
3
- export { CHECKBOX_VARIANTS, CHECKBOX_LABEL_POSITION } from './constants';
4
- export { CheckboxConfig, CheckboxComponent } from './types';
3
+ export { CheckboxConfig, CheckboxComponent, CheckboxVariant, CheckboxLabelPosition } from './types';
@@ -1,5 +1,14 @@
1
1
  // src/components/checkbox/types.ts
2
- import { CHECKBOX_VARIANTS, CHECKBOX_LABEL_POSITION } from './constants';
2
+
3
+ /**
4
+ * Checkbox variant types
5
+ */
6
+ export type CheckboxVariant = 'filled' | 'outlined';
7
+
8
+ /**
9
+ * Checkbox label position types
10
+ */
11
+ export type CheckboxLabelPosition = 'start' | 'end';
3
12
 
4
13
  /**
5
14
  * Configuration interface for the Checkbox component
@@ -27,10 +36,10 @@ export interface CheckboxConfig {
27
36
  label?: string;
28
37
 
29
38
  /** Label position (start/end) */
30
- labelPosition?: keyof typeof CHECKBOX_LABEL_POSITION | string;
39
+ labelPosition?: CheckboxLabelPosition | string;
31
40
 
32
41
  /** Visual variant */
33
- variant?: keyof typeof CHECKBOX_VARIANTS | string;
42
+ variant?: CheckboxVariant | string;
34
43
 
35
44
  /** Additional CSS classes */
36
45
  class?: string;
@@ -1,244 +1,193 @@
1
- // src/components/chip/api.js
1
+ // src/components/chip/api.ts
2
+ import { ApiOptions, ChipComponent } from './types'
3
+
4
+ interface ComponentWithElements {
5
+ element: HTMLElement;
6
+ text?: {
7
+ setText: (content: string) => any;
8
+ getText: () => string;
9
+ getElement: () => HTMLElement | null;
10
+ };
11
+ icon?: {
12
+ setIcon: (html: string) => any;
13
+ getIcon: () => string;
14
+ getElement: () => HTMLElement | null;
15
+ };
16
+ getClass: (name: string) => string;
17
+ }
2
18
 
3
19
  /**
4
20
  * Enhances a chip component with API methods
5
- * @param {Object} options - API configuration options
6
- * @param {Object} options.disabled - Object containing enable/disable methods
7
- * @param {Object} options.lifecycle - Object containing lifecycle methods
21
+ * @param {ApiOptions} options - API configuration options
8
22
  * @returns {Function} Higher-order function that adds API methods to component
9
23
  * @internal This is an internal utility for the Chip component
10
24
  */
11
- export const withAPI = ({ disabled, lifecycle }) => (component) => {
12
- // Track selected state internally
13
- let isSelected = component.element.classList.contains(`${component.getClass('chip')}--selected`);
14
-
15
- return {
16
- ...component,
17
- element: component.element,
18
-
19
- /**
20
- * Gets the chip's value
21
- * @returns {string} The chip's value attribute
22
- */
23
- getValue() {
24
- return component.element.getAttribute('data-value') || '';
25
- },
26
-
27
- /**
28
- * Sets the chip's value
29
- * @param {string} value - Value to set
30
- * @returns {Object} The chip instance for chaining
31
- */
32
- setValue(value) {
33
- component.element.setAttribute('data-value', value || '');
34
- return this;
35
- },
36
-
37
- /**
38
- * Checks if the chip is disabled
39
- * @returns {boolean} True if the chip is disabled
40
- */
41
- isDisabled() {
42
- return component.element.getAttribute('aria-disabled') === 'true';
43
- },
44
-
45
- /**
46
- * Enables the chip
47
- * @returns {Object} The chip instance for chaining
48
- */
49
- enable() {
50
- disabled.enable();
51
- component.element.classList.remove(`${component.getClass('chip')}--disabled`);
52
- component.element.setAttribute('aria-disabled', 'false');
53
- component.element.setAttribute('tabindex', '0');
54
- return this;
55
- },
56
-
57
- /**
58
- * Disables the chip
59
- * @returns {Object} The chip instance for chaining
60
- */
61
- disable() {
62
- disabled.disable();
63
- component.element.classList.add(`${component.getClass('chip')}--disabled`);
64
- component.element.setAttribute('aria-disabled', 'true');
65
- component.element.setAttribute('tabindex', '-1');
66
- return this;
67
- },
68
-
69
- /**
70
- * Sets the chip's text content
71
- * @param {string} content - Text content
72
- * @returns {Object} The chip instance for chaining
73
- */
74
- setText(content) {
75
- const containerSelector = `.${component.getClass('chip')}-content`;
76
- const contentContainer = component.element.querySelector(containerSelector) || component.element;
25
+ export const withAPI = ({ disabled, lifecycle }: ApiOptions) =>
26
+ (component: ComponentWithElements): ChipComponent => {
27
+ // Track selected state internally
28
+ let isSelected = component.element.classList.contains(`${component.getClass('chip')}--selected`);
29
+
30
+ return {
31
+ ...component as any,
32
+ element: component.element,
33
+
34
+ getValue() {
35
+ return component.element.getAttribute('data-value') || null;
36
+ },
37
+
38
+ setValue(value: string) {
39
+ component.element.setAttribute('data-value', value || '');
40
+ return this;
41
+ },
77
42
 
78
- const textSelector = `.${component.getClass('chip')}-text`;
79
- let textElement = component.element.querySelector(textSelector);
43
+ isDisabled() {
44
+ return component.element.getAttribute('aria-disabled') === 'true';
45
+ },
80
46
 
81
- if (!textElement && content) {
82
- textElement = document.createElement('span');
83
- textElement.className = `${component.getClass('chip')}-text`;
47
+ enable() {
48
+ disabled.enable();
49
+ component.element.classList.remove(`${component.getClass('chip')}--disabled`);
50
+ component.element.setAttribute('aria-disabled', 'false');
51
+ component.element.setAttribute('tabindex', '0');
52
+ return this;
53
+ },
54
+
55
+ disable() {
56
+ disabled.disable();
57
+ component.element.classList.add(`${component.getClass('chip')}--disabled`);
58
+ component.element.setAttribute('aria-disabled', 'true');
59
+ component.element.setAttribute('tabindex', '-1');
60
+ return this;
61
+ },
62
+
63
+ setText(content: string) {
64
+ const containerSelector = `.${component.getClass('chip')}-content`;
65
+ const contentContainer = component.element.querySelector(containerSelector) || component.element;
84
66
 
85
- // Find the right position to insert (after leading icon if present, or as first child)
86
- const leadingIcon = component.element.querySelector(`.${component.getClass('chip')}-leading-icon`);
87
- if (leadingIcon) {
88
- contentContainer.insertBefore(textElement, leadingIcon.nextSibling);
89
- } else {
90
- contentContainer.insertBefore(textElement, contentContainer.firstChild);
67
+ const textSelector = `.${component.getClass('chip')}-text`;
68
+ let textElement = component.element.querySelector(textSelector);
69
+
70
+ if (!textElement && content) {
71
+ textElement = document.createElement('span');
72
+ textElement.className = `${component.getClass('chip')}-text`;
73
+
74
+ // Find the right position to insert (after leading icon if present, or as first child)
75
+ const leadingIcon = component.element.querySelector(`.${component.getClass('chip')}-leading-icon`);
76
+ if (leadingIcon) {
77
+ contentContainer.insertBefore(textElement, leadingIcon.nextSibling);
78
+ } else {
79
+ contentContainer.insertBefore(textElement, contentContainer.firstChild);
80
+ }
91
81
  }
92
- }
93
-
94
- if (textElement) {
95
- textElement.textContent = content || '';
96
82
 
97
- // Remove the element if content is empty
98
- if (!content && textElement.parentNode) {
99
- textElement.parentNode.removeChild(textElement);
83
+ if (textElement) {
84
+ textElement.textContent = content || '';
85
+
86
+ // Remove the element if content is empty
87
+ if (!content && textElement.parentNode) {
88
+ textElement.parentNode.removeChild(textElement);
89
+ }
100
90
  }
101
- }
91
+
92
+ return this;
93
+ },
102
94
 
103
- return this;
104
- },
105
-
106
- /**
107
- * Gets the chip's text content
108
- * @returns {string} The chip's text content
109
- */
110
- getText() {
111
- const textElement = component.element.querySelector(`.${component.getClass('chip')}-text`);
112
- return textElement ? textElement.textContent : '';
113
- },
114
-
115
- /**
116
- * Sets the chip's leading icon (alias for setLeadingIcon)
117
- * @param {string} icon - Icon HTML content
118
- * @returns {Object} The chip instance for chaining
119
- */
120
- setIcon(icon) {
121
- return this.setLeadingIcon(icon);
122
- },
123
-
124
- /**
125
- * Gets the chip's icon content
126
- * @returns {string} The chip's icon HTML
127
- */
128
- getIcon() {
129
- const iconElement = component.element.querySelector(`.${component.getClass('chip')}-leading-icon`);
130
- return iconElement ? iconElement.innerHTML : '';
131
- },
132
-
133
- /**
134
- * Sets the chip's leading icon
135
- * @param {string} icon - Icon HTML content
136
- * @returns {Object} The chip instance for chaining
137
- */
138
- setLeadingIcon(icon) {
139
- const contentContainer = component.element.querySelector(`.${component.getClass('chip')}-content`) || component.element;
140
- const leadingIconSelector = `.${component.getClass('chip')}-leading-icon`;
141
- let leadingIconElement = component.element.querySelector(leadingIconSelector);
142
-
143
- if (!leadingIconElement && icon) {
144
- leadingIconElement = document.createElement('span');
145
- leadingIconElement.className = `${component.getClass('chip')}-leading-icon`;
95
+ getText() {
96
+ const textElement = component.element.querySelector(`.${component.getClass('chip')}-text`);
97
+ return textElement ? textElement.textContent || '' : '';
98
+ },
99
+
100
+ setIcon(icon: string) {
101
+ return this.setLeadingIcon(icon);
102
+ },
103
+
104
+ getIcon() {
105
+ const iconElement = component.element.querySelector(`.${component.getClass('chip')}-leading-icon`);
106
+ return iconElement ? iconElement.innerHTML : '';
107
+ },
108
+
109
+ setLeadingIcon(icon: string) {
110
+ const contentContainer = component.element.querySelector(`.${component.getClass('chip')}-content`) || component.element;
111
+ const leadingIconSelector = `.${component.getClass('chip')}-leading-icon`;
112
+ let leadingIconElement = component.element.querySelector(leadingIconSelector);
146
113
 
147
- // Insert as first child of the content container
148
- contentContainer.insertBefore(leadingIconElement, contentContainer.firstChild);
149
- }
150
-
151
- if (leadingIconElement) {
152
- leadingIconElement.innerHTML = icon || '';
114
+ if (!leadingIconElement && icon) {
115
+ leadingIconElement = document.createElement('span');
116
+ leadingIconElement.className = `${component.getClass('chip')}-leading-icon`;
117
+
118
+ // Insert as first child of the content container
119
+ contentContainer.insertBefore(leadingIconElement, contentContainer.firstChild);
120
+ }
153
121
 
154
- // Remove the element if icon is empty
155
- if (!icon && leadingIconElement.parentNode) {
156
- leadingIconElement.parentNode.removeChild(leadingIconElement);
122
+ if (leadingIconElement) {
123
+ leadingIconElement.innerHTML = icon || '';
124
+
125
+ // Remove the element if icon is empty
126
+ if (!icon && leadingIconElement.parentNode) {
127
+ leadingIconElement.parentNode.removeChild(leadingIconElement);
128
+ }
157
129
  }
158
- }
159
-
160
- return this;
161
- },
162
-
163
- /**
164
- * Sets the chip's trailing icon
165
- * @param {string} icon - Icon HTML content
166
- * @param {Function} [onClick] - Click handler for the trailing icon
167
- * @returns {Object} The chip instance for chaining
168
- */
169
- setTrailingIcon(icon, onClick) {
170
- const contentContainer = component.element.querySelector(`.${component.getClass('chip')}-content`) || component.element;
171
- const trailingIconSelector = `.${component.getClass('chip')}-trailing-icon`;
172
- let trailingIconElement = component.element.querySelector(trailingIconSelector);
173
-
174
- if (!trailingIconElement && icon) {
175
- trailingIconElement = document.createElement('span');
176
- trailingIconElement.className = `${component.getClass('chip')}-trailing-icon`;
177
130
 
178
- // Add as last child of content container
179
- contentContainer.appendChild(trailingIconElement);
131
+ return this;
132
+ },
133
+
134
+ setTrailingIcon(icon: string, onClick?: (chip: ChipComponent) => void) {
135
+ const contentContainer = component.element.querySelector(`.${component.getClass('chip')}-content`) || component.element;
136
+ const trailingIconSelector = `.${component.getClass('chip')}-trailing-icon`;
137
+ let trailingIconElement = component.element.querySelector(trailingIconSelector);
180
138
 
181
- // Add click handler if provided
182
- if (onClick) {
183
- trailingIconElement.addEventListener('click', (e) => {
184
- e.stopPropagation(); // Prevent chip click event
185
- onClick(this);
186
- });
139
+ if (!trailingIconElement && icon) {
140
+ trailingIconElement = document.createElement('span');
141
+ trailingIconElement.className = `${component.getClass('chip')}-trailing-icon`;
142
+
143
+ // Add as last child of content container
144
+ contentContainer.appendChild(trailingIconElement);
145
+
146
+ // Add click handler if provided
147
+ if (onClick) {
148
+ trailingIconElement.addEventListener('click', (e) => {
149
+ e.stopPropagation(); // Prevent chip click event
150
+ onClick(this as unknown as ChipComponent);
151
+ });
152
+ }
187
153
  }
188
- }
189
-
190
- if (trailingIconElement) {
191
- trailingIconElement.innerHTML = icon || '';
192
154
 
193
- // Remove the element if icon is empty
194
- if (!icon && trailingIconElement.parentNode) {
195
- trailingIconElement.parentNode.removeChild(trailingIconElement);
155
+ if (trailingIconElement) {
156
+ trailingIconElement.innerHTML = icon || '';
157
+
158
+ // Remove the element if icon is empty
159
+ if (!icon && trailingIconElement.parentNode) {
160
+ trailingIconElement.parentNode.removeChild(trailingIconElement);
161
+ }
196
162
  }
197
- }
198
-
199
- return this;
200
- },
201
-
202
- /**
203
- * Checks if the chip is selected
204
- * @returns {boolean} True if the chip is selected
205
- */
206
- isSelected() {
207
- return isSelected;
208
- },
209
-
210
- /**
211
- * Sets the chip's selected state
212
- * @param {boolean} selected - Whether the chip should be selected
213
- * @returns {Object} The chip instance for chaining
214
- */
215
- setSelected(selected) {
216
- isSelected = !!selected;
163
+
164
+ return this;
165
+ },
217
166
 
218
- if (selected) {
219
- component.element.classList.add(`${component.getClass('chip')}--selected`);
220
- component.element.setAttribute('aria-selected', 'true');
221
- } else {
222
- component.element.classList.remove(`${component.getClass('chip')}--selected`);
223
- component.element.setAttribute('aria-selected', 'false');
224
- }
167
+ isSelected() {
168
+ return isSelected;
169
+ },
225
170
 
226
- return this;
227
- },
228
-
229
- /**
230
- * Toggles the chip's selected state
231
- * @returns {Object} The chip instance for chaining
232
- */
233
- toggleSelected() {
234
- return this.setSelected(!isSelected);
235
- },
236
-
237
- /**
238
- * Destroys the chip component and cleans up resources
239
- */
240
- destroy() {
241
- lifecycle.destroy();
242
- }
243
- };
244
- };
171
+ setSelected(selected: boolean) {
172
+ isSelected = !!selected;
173
+
174
+ if (selected) {
175
+ component.element.classList.add(`${component.getClass('chip')}--selected`);
176
+ component.element.setAttribute('aria-selected', 'true');
177
+ } else {
178
+ component.element.classList.remove(`${component.getClass('chip')}--selected`);
179
+ component.element.setAttribute('aria-selected', 'false');
180
+ }
181
+
182
+ return this;
183
+ },
184
+
185
+ toggleSelected() {
186
+ return this.setSelected(!isSelected);
187
+ },
188
+
189
+ destroy() {
190
+ lifecycle.destroy();
191
+ }
192
+ } as unknown as ChipComponent;
193
+ };