mtrl 0.2.6 → 0.2.7

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 (147) hide show
  1. package/index.ts +18 -0
  2. package/package.json +1 -1
  3. package/src/components/badge/_styles.scss +117 -109
  4. package/src/components/badge/api.ts +57 -59
  5. package/src/components/badge/badge.ts +16 -2
  6. package/src/components/badge/config.ts +65 -11
  7. package/src/components/badge/constants.ts +22 -12
  8. package/src/components/badge/features.ts +44 -40
  9. package/src/components/badge/types.ts +42 -30
  10. package/src/components/bottom-app-bar/_styles.scss +103 -0
  11. package/src/components/bottom-app-bar/bottom-app-bar.ts +196 -0
  12. package/src/components/bottom-app-bar/config.ts +73 -0
  13. package/src/components/bottom-app-bar/index.ts +11 -0
  14. package/src/components/bottom-app-bar/types.ts +108 -0
  15. package/src/components/button/_styles.scss +0 -10
  16. package/src/components/button/api.ts +5 -0
  17. package/src/components/button/config.ts +5 -0
  18. package/src/components/button/types.ts +6 -0
  19. package/src/components/card/card.ts +13 -25
  20. package/src/components/card/config.ts +67 -22
  21. package/src/components/card/features.ts +3 -0
  22. package/src/components/card/types.ts +28 -0
  23. package/src/components/checkbox/_styles.scss +0 -2
  24. package/src/components/datepicker/_styles.scss +358 -0
  25. package/src/components/datepicker/api.ts +272 -0
  26. package/src/components/datepicker/config.ts +144 -0
  27. package/src/components/datepicker/constants.ts +98 -0
  28. package/src/components/datepicker/datepicker.ts +346 -0
  29. package/src/components/datepicker/index.ts +9 -0
  30. package/src/components/datepicker/render.ts +452 -0
  31. package/src/components/datepicker/types.ts +268 -0
  32. package/src/components/datepicker/utils.ts +290 -0
  33. package/src/components/dialog/_styles.scss +174 -128
  34. package/src/components/dialog/api.ts +48 -13
  35. package/src/components/dialog/config.ts +9 -5
  36. package/src/components/dialog/dialog.ts +6 -3
  37. package/src/components/dialog/features.ts +290 -130
  38. package/src/components/dialog/types.ts +7 -4
  39. package/src/components/divider/_styles.scss +57 -0
  40. package/src/components/divider/config.ts +81 -0
  41. package/src/components/divider/divider.ts +37 -0
  42. package/src/components/divider/features.ts +207 -0
  43. package/src/components/divider/index.ts +5 -0
  44. package/src/components/divider/types.ts +55 -0
  45. package/src/components/extended-fab/_styles.scss +267 -0
  46. package/src/components/extended-fab/api.ts +141 -0
  47. package/src/components/extended-fab/config.ts +108 -0
  48. package/src/components/extended-fab/constants.ts +36 -0
  49. package/src/components/extended-fab/extended-fab.ts +125 -0
  50. package/src/components/extended-fab/index.ts +4 -0
  51. package/src/components/extended-fab/types.ts +287 -0
  52. package/src/components/fab/_styles.scss +225 -0
  53. package/src/components/fab/api.ts +97 -0
  54. package/src/components/fab/config.ts +94 -0
  55. package/src/components/fab/constants.ts +41 -0
  56. package/src/components/fab/fab.ts +67 -0
  57. package/src/components/fab/index.ts +4 -0
  58. package/src/components/fab/types.ts +234 -0
  59. package/src/components/navigation/_styles.scss +1 -0
  60. package/src/components/navigation/api.ts +78 -50
  61. package/src/components/navigation/features/items.ts +280 -0
  62. package/src/components/navigation/nav-item.ts +72 -23
  63. package/src/components/navigation/navigation.ts +54 -2
  64. package/src/components/navigation/types.ts +210 -188
  65. package/src/components/search/_styles.scss +306 -0
  66. package/src/components/search/api.ts +203 -0
  67. package/src/components/search/config.ts +87 -0
  68. package/src/components/search/constants.ts +21 -0
  69. package/src/components/search/features/index.ts +4 -0
  70. package/src/components/search/features/search.ts +718 -0
  71. package/src/components/search/features/states.ts +165 -0
  72. package/src/components/search/features/structure.ts +198 -0
  73. package/src/components/search/index.ts +10 -0
  74. package/src/components/search/search.ts +52 -0
  75. package/src/components/search/types.ts +163 -0
  76. package/src/components/segmented-button/_styles.scss +117 -0
  77. package/src/components/segmented-button/config.ts +67 -0
  78. package/src/components/segmented-button/constants.ts +42 -0
  79. package/src/components/segmented-button/index.ts +4 -0
  80. package/src/components/segmented-button/segment.ts +155 -0
  81. package/src/components/segmented-button/segmented-button.ts +250 -0
  82. package/src/components/segmented-button/types.ts +219 -0
  83. package/src/components/slider/_styles.scss +83 -24
  84. package/src/components/slider/accessibility.md +5 -5
  85. package/src/components/slider/api.ts +41 -120
  86. package/src/components/slider/config.ts +51 -47
  87. package/src/components/slider/features/handlers.ts +495 -0
  88. package/src/components/slider/features/index.ts +1 -2
  89. package/src/components/slider/features/slider.ts +66 -84
  90. package/src/components/slider/features/states.ts +195 -0
  91. package/src/components/slider/features/structure.ts +136 -206
  92. package/src/components/slider/features/ui.ts +145 -206
  93. package/src/components/slider/index.ts +2 -11
  94. package/src/components/slider/slider.ts +9 -12
  95. package/src/components/slider/types.ts +39 -24
  96. package/src/components/switch/_styles.scss +0 -2
  97. package/src/components/tabs/_styles.scss +94 -32
  98. package/src/components/tabs/features.ts +4 -2
  99. package/src/components/tabs/indicator.ts +73 -13
  100. package/src/components/tabs/types.ts +10 -2
  101. package/src/components/timepicker/README.md +277 -0
  102. package/src/components/timepicker/_styles.scss +451 -0
  103. package/src/components/timepicker/api.ts +632 -0
  104. package/src/components/timepicker/clockdial.ts +482 -0
  105. package/src/components/timepicker/config.ts +130 -0
  106. package/src/components/timepicker/constants.ts +138 -0
  107. package/src/components/timepicker/index.ts +8 -0
  108. package/src/components/timepicker/render.ts +613 -0
  109. package/src/components/timepicker/timepicker.ts +117 -0
  110. package/src/components/timepicker/types.ts +336 -0
  111. package/src/components/timepicker/utils.ts +241 -0
  112. package/src/components/top-app-bar/_styles.scss +225 -0
  113. package/src/components/top-app-bar/config.ts +83 -0
  114. package/src/components/top-app-bar/index.ts +11 -0
  115. package/src/components/top-app-bar/top-app-bar.ts +316 -0
  116. package/src/components/top-app-bar/types.ts +140 -0
  117. package/src/core/build/_ripple.scss +6 -6
  118. package/src/core/build/ripple.ts +72 -95
  119. package/src/core/compose/features/icon.ts +3 -1
  120. package/src/core/compose/features/ripple.ts +4 -1
  121. package/src/core/compose/features/textlabel.ts +26 -2
  122. package/src/core/dom/create.ts +5 -0
  123. package/src/index.ts +9 -0
  124. package/src/styles/abstract/_theme.scss +9 -1
  125. package/src/styles/themes/_autumn.scss +21 -0
  126. package/src/styles/themes/_base-theme.scss +61 -0
  127. package/src/styles/themes/_baseline.scss +58 -0
  128. package/src/styles/themes/_bluekhaki.scss +125 -0
  129. package/src/styles/themes/_brownbeige.scss +125 -0
  130. package/src/styles/themes/_browngreen.scss +125 -0
  131. package/src/styles/themes/_forest.scss +6 -0
  132. package/src/styles/themes/_greenbeige.scss +125 -0
  133. package/src/styles/themes/_material.scss +125 -0
  134. package/src/styles/themes/_ocean.scss +6 -0
  135. package/src/styles/themes/_sageivory.scss +125 -0
  136. package/src/styles/themes/_spring.scss +6 -0
  137. package/src/styles/themes/_summer.scss +5 -0
  138. package/src/styles/themes/_sunset.scss +5 -0
  139. package/src/styles/themes/_tealcaramel.scss +125 -0
  140. package/src/styles/themes/_winter.scss +6 -0
  141. package/src/components/navigation/features/items.js +0 -192
  142. package/src/components/slider/features/appearance.ts +0 -94
  143. package/src/components/slider/features/disabled.ts +0 -68
  144. package/src/components/slider/features/events.ts +0 -164
  145. package/src/components/slider/features/interactions.ts +0 -396
  146. package/src/components/slider/features/keyboard.ts +0 -233
  147. package/src/core/collection/adapters/mongodb.js +0 -232
@@ -0,0 +1,225 @@
1
+ // src/components/fab/_styles.scss
2
+ @use '../../styles/abstract/base' as base;
3
+ @use '../../styles/abstract/variables' as v;
4
+ @use '../../styles/abstract/functions' as f;
5
+ @use '../../styles/abstract/mixins' as m;
6
+ @use '../../styles/abstract/theme' as t;
7
+
8
+ $component: '#{base.$prefix}-fab';
9
+
10
+ .#{$component} {
11
+ // Base styles
12
+ position: relative;
13
+ display: inline-flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ border: none;
17
+ background-color: t.color('primary-container');
18
+ color: t.color('on-primary-container');
19
+ font: inherit;
20
+ text-decoration: none;
21
+ cursor: pointer;
22
+ user-select: none;
23
+ vertical-align: middle;
24
+ appearance: none;
25
+ overflow: hidden;
26
+
27
+ // FAB uses elevation in all variants
28
+ @include m.elevation(3);
29
+
30
+ // Transitions
31
+ @include m.motion-transition(
32
+ transform,
33
+ box-shadow,
34
+ background-color,
35
+ color
36
+ );
37
+
38
+ // Focus styles
39
+ &:focus {
40
+ outline: none;
41
+ }
42
+
43
+ &:focus-visible {
44
+ outline: 2px solid t.color('outline');
45
+ outline-offset: 2px;
46
+ }
47
+
48
+ // Default FAB size (56dp)
49
+ width: 56px;
50
+ height: 56px;
51
+ border-radius: f.get-shape('large');
52
+
53
+ // Icon sizing
54
+ &-icon {
55
+ display: inline-flex;
56
+ align-items: center;
57
+ justify-content: center;
58
+ width: 24px;
59
+ height: 24px;
60
+
61
+ svg {
62
+ width: 24px;
63
+ height: 24px;
64
+ }
65
+ }
66
+
67
+ // Size variants
68
+ &--small {
69
+ width: 40px;
70
+ height: 40px;
71
+ border-radius: f.get-shape('medium');
72
+
73
+ .#{$component}-icon {
74
+ width: 24px;
75
+ height: 24px;
76
+
77
+ svg {
78
+ width: 24px;
79
+ height: 24px;
80
+ }
81
+ }
82
+ }
83
+
84
+ &--default {
85
+ // Default is already defined in base styles
86
+ }
87
+
88
+ &--large {
89
+ width: 96px;
90
+ height: 96px;
91
+ border-radius: f.get-shape('extra-large');
92
+
93
+ .#{$component}-icon {
94
+ width: 36px;
95
+ height: 36px;
96
+
97
+ svg {
98
+ width: 36px;
99
+ height: 36px;
100
+ }
101
+ }
102
+ }
103
+
104
+ // Color variants - primary is the default
105
+
106
+ // Primary variant (default)
107
+ &--primary {
108
+ background-color: t.color('primary-container');
109
+ color: t.color('on-primary-container');
110
+
111
+ &:hover {
112
+ @include m.state-layer(t.color('on-primary-container'), 'hover');
113
+ }
114
+
115
+ &:active {
116
+ @include m.state-layer(t.color('on-primary-container'), 'pressed');
117
+ @include m.elevation(1);
118
+ }
119
+ }
120
+
121
+ // Secondary variant
122
+ &--secondary {
123
+ background-color: t.color('secondary-container');
124
+ color: t.color('on-secondary-container');
125
+
126
+ &:hover {
127
+ @include m.state-layer(t.color('on-secondary-container'), 'hover');
128
+ }
129
+
130
+ &:active {
131
+ @include m.state-layer(t.color('on-secondary-container'), 'pressed');
132
+ @include m.elevation(1);
133
+ }
134
+ }
135
+
136
+ // Tertiary variant
137
+ &--tertiary {
138
+ background-color: t.color('tertiary-container');
139
+ color: t.color('on-tertiary-container');
140
+
141
+ &:hover {
142
+ @include m.state-layer(t.color('on-tertiary-container'), 'hover');
143
+ }
144
+
145
+ &:active {
146
+ @include m.state-layer(t.color('on-tertiary-container'), 'pressed');
147
+ @include m.elevation(1);
148
+ }
149
+ }
150
+
151
+ // Surface variant
152
+ &--surface {
153
+ background-color: t.color('surface');
154
+ color: t.color('primary');
155
+
156
+ &:hover {
157
+ @include m.state-layer(t.color('primary'), 'hover');
158
+ }
159
+
160
+ &:active {
161
+ @include m.state-layer(t.color('primary'), 'pressed');
162
+ @include m.elevation(1);
163
+ }
164
+ }
165
+
166
+ // Lowered state (when pressed)
167
+ &--lowered {
168
+ @include m.elevation(1);
169
+ transform: translateY(1px);
170
+ }
171
+
172
+ // Disabled state
173
+ &--disabled,
174
+ &:disabled {
175
+ pointer-events: none;
176
+ @include m.elevation(0);
177
+ background-color: t.alpha('on-surface', 0.12);
178
+ color: t.alpha('on-surface', 0.38);
179
+ }
180
+
181
+ // Positioning utilities
182
+ &--top-right {
183
+ position: fixed;
184
+ top: 16px;
185
+ right: 16px;
186
+ z-index: v.z-index('dropdown');
187
+ }
188
+
189
+ &--top-left {
190
+ position: fixed;
191
+ top: 16px;
192
+ left: 16px;
193
+ z-index: v.z-index('dropdown');
194
+ }
195
+
196
+ &--bottom-right {
197
+ position: fixed;
198
+ bottom: 16px;
199
+ right: 16px;
200
+ z-index: v.z-index('dropdown');
201
+ }
202
+
203
+ &--bottom-left {
204
+ position: fixed;
205
+ bottom: 16px;
206
+ left: 16px;
207
+ z-index: v.z-index('dropdown');
208
+ }
209
+
210
+ // Optional animations
211
+ @keyframes fab-enter {
212
+ from {
213
+ transform: scale(0);
214
+ opacity: 0;
215
+ }
216
+ to {
217
+ transform: scale(1);
218
+ opacity: 1;
219
+ }
220
+ }
221
+
222
+ &--animate-enter {
223
+ animation: fab-enter 0.3s f.get-motion-easing('emphasized-decelerate') forwards;
224
+ }
225
+ }
@@ -0,0 +1,97 @@
1
+ // src/components/fab/api.ts
2
+ import { FabComponent } from './types';
3
+
4
+ interface ApiOptions {
5
+ disabled: {
6
+ enable: () => void;
7
+ disable: () => void;
8
+ };
9
+ lifecycle: {
10
+ destroy: () => void;
11
+ };
12
+ className: string;
13
+ }
14
+
15
+ interface ComponentWithElements {
16
+ element: HTMLElement;
17
+ icon: {
18
+ setIcon: (html: string) => any;
19
+ getIcon: () => string;
20
+ getElement: () => HTMLElement | null;
21
+ };
22
+ getClass: (name: string) => string;
23
+ }
24
+
25
+ /**
26
+ * Enhances a FAB component with API methods
27
+ * @param {ApiOptions} options - API configuration options
28
+ * @returns {Function} Higher-order function that adds API methods to component
29
+ * @internal This is an internal utility for the FAB component
30
+ */
31
+ export const withAPI = ({ disabled, lifecycle, className }: ApiOptions) =>
32
+ (component: ComponentWithElements): FabComponent => ({
33
+ ...component as any,
34
+ element: component.element as HTMLButtonElement,
35
+
36
+ getValue: () => component.element.value,
37
+
38
+ setValue(value: string) {
39
+ component.element.value = value;
40
+ return this;
41
+ },
42
+
43
+ enable() {
44
+ disabled.enable();
45
+ return this;
46
+ },
47
+
48
+ disable() {
49
+ disabled.disable();
50
+ return this;
51
+ },
52
+
53
+ setIcon(icon: string) {
54
+ component.icon.setIcon(icon);
55
+ return this;
56
+ },
57
+
58
+ getIcon() {
59
+ return component.icon.getIcon();
60
+ },
61
+
62
+ setPosition(position: string) {
63
+ // First remove any existing position classes
64
+ const positions = ['top-right', 'top-left', 'bottom-right', 'bottom-left'];
65
+ positions.forEach(pos => {
66
+ component.element.classList.remove(`${className}--${pos}`);
67
+ });
68
+
69
+ // Add new position class
70
+ component.element.classList.add(`${className}--${position}`);
71
+ return this;
72
+ },
73
+
74
+ getPosition() {
75
+ const positions = ['top-right', 'top-left', 'bottom-right', 'bottom-left'];
76
+ for (const pos of positions) {
77
+ if (component.element.classList.contains(`${className}--${pos}`)) {
78
+ return pos;
79
+ }
80
+ }
81
+ return null;
82
+ },
83
+
84
+ lower() {
85
+ component.element.classList.add(`${className}--lowered`);
86
+ return this;
87
+ },
88
+
89
+ raise() {
90
+ component.element.classList.remove(`${className}--lowered`);
91
+ return this;
92
+ },
93
+
94
+ destroy() {
95
+ lifecycle.destroy();
96
+ }
97
+ });
@@ -0,0 +1,94 @@
1
+ // src/components/fab/config.ts
2
+ import {
3
+ createComponentConfig,
4
+ createElementConfig,
5
+ BaseComponentConfig
6
+ } from '../../core/config/component-config';
7
+ import { FabConfig } from './types';
8
+ import { FAB_VARIANTS, FAB_SIZES } from './constants';
9
+
10
+ /**
11
+ * Default configuration for the FAB component
12
+ */
13
+ export const defaultConfig: FabConfig = {
14
+ variant: FAB_VARIANTS.PRIMARY,
15
+ size: FAB_SIZES.DEFAULT,
16
+ type: 'button',
17
+ ripple: true
18
+ };
19
+
20
+ /**
21
+ * Creates the base configuration for FAB component
22
+ * @param {FabConfig} config - User provided configuration
23
+ * @returns {FabConfig} Complete configuration with defaults applied
24
+ */
25
+ export const createBaseConfig = (config: FabConfig = {}): FabConfig =>
26
+ createComponentConfig(defaultConfig, config, 'fab') as FabConfig;
27
+
28
+ /**
29
+ * Generates element configuration for the FAB component
30
+ * @param {FabConfig} config - FAB configuration
31
+ * @returns {Object} Element configuration object for withElement
32
+ */
33
+ export const getElementConfig = (config: FabConfig) => {
34
+ // Create the attributes object
35
+ const attrs: Record<string, any> = {
36
+ type: config.type || 'button',
37
+ 'aria-label': config.ariaLabel || (config.icon ? 'action' : undefined)
38
+ };
39
+
40
+ // Add size class
41
+ const fabSizeClass = `${config.prefix}-fab--${config.size || FAB_SIZES.DEFAULT}`;
42
+ let classNames = [fabSizeClass];
43
+
44
+ // Add animation class if specified
45
+ if (config.animate) {
46
+ classNames.push(`${config.prefix}-fab--animate-enter`);
47
+ }
48
+
49
+ // Add position class if specified
50
+ if (config.position) {
51
+ classNames.push(`${config.prefix}-fab--${config.position}`);
52
+ }
53
+
54
+ // Add user classes
55
+ if (config.class) {
56
+ classNames.push(config.class);
57
+ }
58
+
59
+ // Only add disabled attribute if it's explicitly true
60
+ if (config.disabled === true) {
61
+ attrs.disabled = true;
62
+ classNames.push(`${config.prefix}-fab--disabled`);
63
+ }
64
+
65
+ return createElementConfig(config, {
66
+ tag: 'button',
67
+ attrs,
68
+ className: classNames,
69
+ forwardEvents: {
70
+ click: (component) => !component.element.disabled,
71
+ focus: true,
72
+ blur: true
73
+ },
74
+ interactive: true
75
+ });
76
+ };
77
+
78
+ /**
79
+ * Creates API configuration for the FAB component
80
+ * @param {Object} comp - Component with disabled and lifecycle features
81
+ * @returns {Object} API configuration object
82
+ */
83
+ export const getApiConfig = (comp: any) => ({
84
+ disabled: {
85
+ enable: () => comp.disabled.enable(),
86
+ disable: () => comp.disabled.disable()
87
+ },
88
+ lifecycle: {
89
+ destroy: () => comp.lifecycle.destroy()
90
+ },
91
+ className: comp.getClass('fab')
92
+ });
93
+
94
+ export default defaultConfig;
@@ -0,0 +1,41 @@
1
+ // src/components/fab/constants.ts
2
+
3
+ /**
4
+ * FAB variants for styling
5
+ */
6
+ export const FAB_VARIANTS = {
7
+ /** Primary container color with on-primary-container icons */
8
+ PRIMARY: 'primary',
9
+ /** Secondary container color with on-secondary-container icons */
10
+ SECONDARY: 'secondary',
11
+ /** Tertiary container color with on-tertiary-container icons */
12
+ TERTIARY: 'tertiary',
13
+ /** Surface color with primary color icons */
14
+ SURFACE: 'surface'
15
+ };
16
+
17
+ /**
18
+ * FAB size variants
19
+ */
20
+ export const FAB_SIZES = {
21
+ /** Standard FAB size (56dp) */
22
+ DEFAULT: 'default',
23
+ /** Small FAB size (40dp) */
24
+ SMALL: 'small',
25
+ /** Large FAB size (96dp) */
26
+ LARGE: 'large'
27
+ };
28
+
29
+ /**
30
+ * FAB positions for fixed positioning
31
+ */
32
+ export const FAB_POSITIONS = {
33
+ /** Top right corner */
34
+ TOP_RIGHT: 'top-right',
35
+ /** Top left corner */
36
+ TOP_LEFT: 'top-left',
37
+ /** Bottom right corner */
38
+ BOTTOM_RIGHT: 'bottom-right',
39
+ /** Bottom left corner */
40
+ BOTTOM_LEFT: 'bottom-left'
41
+ };
@@ -0,0 +1,67 @@
1
+ // src/components/fab/fab.ts
2
+ import { pipe } from '../../core/compose';
3
+ import { createBase, withElement } from '../../core/compose/component';
4
+ import {
5
+ withEvents,
6
+ withIcon,
7
+ withVariant,
8
+ withRipple,
9
+ withDisabled,
10
+ withLifecycle
11
+ } from '../../core/compose/features';
12
+ import { withAPI } from './api';
13
+ import { FabConfig, FabComponent } from './types';
14
+ import { createBaseConfig, getElementConfig, getApiConfig } from './config';
15
+
16
+ /**
17
+ * Creates a new Floating Action Button (FAB) component
18
+ *
19
+ * @param {FabConfig} config - FAB configuration object
20
+ * @returns {FabComponent} FAB component instance
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * // Create a default FAB with a plus icon
25
+ * const fab = createFab({
26
+ * icon: '<svg>...</svg>',
27
+ * ariaLabel: 'Add new item'
28
+ * });
29
+ *
30
+ * // Create a small FAB with a custom position
31
+ * const smallFab = createFab({
32
+ * size: FAB_SIZES.SMALL,
33
+ * icon: '<svg>...</svg>',
34
+ * variant: 'secondary',
35
+ * position: 'bottom-right'
36
+ * });
37
+ *
38
+ * // Add click handler
39
+ * fab.on('click', () => {
40
+ * console.log('FAB clicked');
41
+ * });
42
+ * ```
43
+ */
44
+ const createFab = (config: FabConfig = {}): FabComponent => {
45
+ const fabConfig = createBaseConfig(config);
46
+
47
+ try {
48
+ const fab = pipe(
49
+ createBase,
50
+ withEvents(),
51
+ withElement(getElementConfig(fabConfig)),
52
+ withVariant(fabConfig),
53
+ withIcon(fabConfig),
54
+ withDisabled(fabConfig),
55
+ withRipple(fabConfig),
56
+ withLifecycle(),
57
+ comp => withAPI(getApiConfig(comp))(comp)
58
+ )(fabConfig);
59
+
60
+ return fab;
61
+ } catch (error) {
62
+ console.error('FAB creation error:', error);
63
+ throw new Error(`Failed to create FAB: ${(error as Error).message}`);
64
+ }
65
+ };
66
+
67
+ export default createFab;
@@ -0,0 +1,4 @@
1
+ // src/components/fab/index.ts
2
+ export { default, default as createFab } from './fab';
3
+ export { FAB_VARIANTS, FAB_SIZES, FAB_POSITIONS } from './constants';
4
+ export { FabConfig, FabComponent } from './types';