mtrl 0.2.2 → 0.2.3

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 (92) hide show
  1. package/.typedocignore +11 -0
  2. package/DOCS.md +153 -0
  3. package/index.ts +18 -3
  4. package/package.json +7 -2
  5. package/src/components/badge/_styles.scss +174 -0
  6. package/src/components/badge/api.ts +292 -0
  7. package/src/components/badge/badge.ts +52 -0
  8. package/src/components/badge/config.ts +68 -0
  9. package/src/components/badge/constants.ts +30 -0
  10. package/src/components/badge/features.ts +185 -0
  11. package/src/components/badge/index.ts +4 -0
  12. package/src/components/badge/types.ts +105 -0
  13. package/src/components/button/types.ts +174 -29
  14. package/src/components/carousel/_styles.scss +645 -0
  15. package/src/components/carousel/api.ts +147 -0
  16. package/src/components/carousel/carousel.ts +178 -0
  17. package/src/components/carousel/config.ts +91 -0
  18. package/src/components/carousel/constants.ts +95 -0
  19. package/src/components/carousel/features/drag.ts +388 -0
  20. package/src/components/carousel/features/index.ts +8 -0
  21. package/src/components/carousel/features/slides.ts +682 -0
  22. package/src/components/carousel/index.ts +38 -0
  23. package/src/components/carousel/types.ts +327 -0
  24. package/src/components/dialog/_styles.scss +213 -0
  25. package/src/components/dialog/api.ts +283 -0
  26. package/src/components/dialog/config.ts +113 -0
  27. package/src/components/dialog/constants.ts +32 -0
  28. package/src/components/dialog/dialog.ts +56 -0
  29. package/src/components/dialog/features.ts +713 -0
  30. package/src/components/dialog/index.ts +15 -0
  31. package/src/components/dialog/types.ts +221 -0
  32. package/src/components/progress/_styles.scss +13 -1
  33. package/src/components/progress/api.ts +2 -2
  34. package/src/components/progress/progress.ts +2 -2
  35. package/src/components/progress/types.ts +3 -0
  36. package/src/components/radios/_styles.scss +232 -0
  37. package/src/components/radios/api.ts +100 -0
  38. package/src/components/radios/config.ts +60 -0
  39. package/src/components/radios/constants.ts +28 -0
  40. package/src/components/radios/index.ts +4 -0
  41. package/src/components/radios/radio.ts +269 -0
  42. package/src/components/radios/radios.ts +42 -0
  43. package/src/components/radios/types.ts +232 -0
  44. package/src/components/sheet/_styles.scss +236 -0
  45. package/src/components/sheet/api.ts +96 -0
  46. package/src/components/sheet/config.ts +66 -0
  47. package/src/components/sheet/constants.ts +20 -0
  48. package/src/components/sheet/features/content.ts +51 -0
  49. package/src/components/sheet/features/gestures.ts +177 -0
  50. package/src/components/sheet/features/index.ts +6 -0
  51. package/src/components/sheet/features/position.ts +42 -0
  52. package/src/components/sheet/features/state.ts +116 -0
  53. package/src/components/sheet/features/title.ts +86 -0
  54. package/src/components/sheet/index.ts +4 -0
  55. package/src/components/sheet/sheet.ts +57 -0
  56. package/src/components/sheet/types.ts +266 -0
  57. package/src/components/slider/_styles.scss +518 -0
  58. package/src/components/slider/api.ts +336 -0
  59. package/src/components/slider/config.ts +145 -0
  60. package/src/components/slider/constants.ts +28 -0
  61. package/src/components/slider/features/appearance.ts +140 -0
  62. package/src/components/slider/features/disabled.ts +43 -0
  63. package/src/components/slider/features/events.ts +164 -0
  64. package/src/components/slider/features/index.ts +5 -0
  65. package/src/components/slider/features/interactions.ts +256 -0
  66. package/src/components/slider/features/keyboard.ts +114 -0
  67. package/src/components/slider/features/slider.ts +336 -0
  68. package/src/components/slider/features/structure.ts +264 -0
  69. package/src/components/slider/features/ui.ts +518 -0
  70. package/src/components/slider/index.ts +9 -0
  71. package/src/components/slider/slider.ts +58 -0
  72. package/src/components/slider/types.ts +166 -0
  73. package/src/components/tabs/_styles.scss +224 -0
  74. package/src/components/tabs/api.ts +443 -0
  75. package/src/components/tabs/config.ts +80 -0
  76. package/src/components/tabs/constants.ts +12 -0
  77. package/src/components/tabs/index.ts +4 -0
  78. package/src/components/tabs/tabs.ts +52 -0
  79. package/src/components/tabs/types.ts +247 -0
  80. package/src/components/textfield/_styles.scss +97 -4
  81. package/src/components/tooltip/_styles.scss +241 -0
  82. package/src/components/tooltip/api.ts +411 -0
  83. package/src/components/tooltip/config.ts +78 -0
  84. package/src/components/tooltip/constants.ts +27 -0
  85. package/src/components/tooltip/index.ts +4 -0
  86. package/src/components/tooltip/tooltip.ts +60 -0
  87. package/src/components/tooltip/types.ts +178 -0
  88. package/src/index.ts +9 -1
  89. package/src/styles/abstract/_variables.scss +24 -12
  90. package/tsconfig.json +22 -0
  91. package/typedoc.json +28 -0
  92. package/typedoc.simple.json +14 -0
@@ -0,0 +1,283 @@
1
+ // src/components/dialog/api.ts
2
+ import { DialogComponent, DialogEvent, DialogButton, DialogConfirmOptions } from './types';
3
+ import { DIALOG_SIZES, DIALOG_ANIMATIONS, DIALOG_FOOTER_ALIGNMENTS, DIALOG_EVENTS } from './constants';
4
+
5
+ interface ApiOptions {
6
+ visibility: {
7
+ open: () => void;
8
+ close: () => void;
9
+ toggle: (open?: boolean) => void;
10
+ isOpen: () => boolean;
11
+ };
12
+ content: {
13
+ setTitle: (title: string) => void;
14
+ getTitle: () => string;
15
+ setSubtitle: (subtitle: string) => void;
16
+ getSubtitle: () => string;
17
+ setContent: (content: string) => void;
18
+ getContent: () => string;
19
+ getHeaderElement: () => HTMLElement | null;
20
+ getContentElement: () => HTMLElement | null;
21
+ getFooterElement: () => HTMLElement | null;
22
+ };
23
+ buttons: {
24
+ addButton: (button: DialogButton) => void;
25
+ removeButton: (indexOrText: number | string) => void;
26
+ getButtons: () => DialogButton[];
27
+ setFooterAlignment: (alignment: keyof typeof DIALOG_FOOTER_ALIGNMENTS | DIALOG_FOOTER_ALIGNMENTS) => void;
28
+ };
29
+ focus: {
30
+ trapFocus: () => void;
31
+ releaseFocus: () => void;
32
+ };
33
+ size: {
34
+ setSize: (size: keyof typeof DIALOG_SIZES | DIALOG_SIZES) => void;
35
+ };
36
+ events: {
37
+ on: (event: string, handler: Function) => void;
38
+ off: (event: string, handler: Function) => void;
39
+ trigger: (event: string, data: any) => void;
40
+ };
41
+ lifecycle: {
42
+ destroy: () => void;
43
+ };
44
+ }
45
+
46
+ interface ComponentWithElements {
47
+ element: HTMLElement;
48
+ overlay: HTMLElement;
49
+ confirm?: (options: DialogConfirmOptions) => Promise<boolean>;
50
+ }
51
+
52
+ /**
53
+ * Enhances a dialog component with API methods
54
+ * @param {ApiOptions} options - API configuration options
55
+ * @returns {Function} Higher-order function that adds API methods to component
56
+ * @internal This is an internal utility for the Dialog component
57
+ */
58
+ export const withAPI = (options: ApiOptions) =>
59
+ (component: ComponentWithElements): DialogComponent => ({
60
+ ...component as any,
61
+
62
+ /**
63
+ * Opens the dialog
64
+ * @returns {DialogComponent} Dialog component instance for chaining
65
+ */
66
+ open() {
67
+ options.visibility.open();
68
+ return this;
69
+ },
70
+
71
+ /**
72
+ * Closes the dialog
73
+ * @returns {DialogComponent} Dialog component instance for chaining
74
+ */
75
+ close() {
76
+ options.visibility.close();
77
+ return this;
78
+ },
79
+
80
+ /**
81
+ * Toggles dialog open/closed state
82
+ * @param {boolean} [open] - Optional flag to force open state
83
+ * @returns {DialogComponent} Dialog component instance for chaining
84
+ */
85
+ toggle(open?: boolean) {
86
+ options.visibility.toggle(open);
87
+ return this;
88
+ },
89
+
90
+ /**
91
+ * Checks if dialog is open
92
+ * @returns {boolean} True if dialog is open
93
+ */
94
+ isOpen() {
95
+ return options.visibility.isOpen();
96
+ },
97
+
98
+ /**
99
+ * Sets dialog title
100
+ * @param {string} title - Title text
101
+ * @returns {DialogComponent} Dialog component instance for chaining
102
+ */
103
+ setTitle(title: string) {
104
+ options.content.setTitle(title);
105
+ return this;
106
+ },
107
+
108
+ /**
109
+ * Gets dialog title
110
+ * @returns {string} Title text
111
+ */
112
+ getTitle() {
113
+ return options.content.getTitle();
114
+ },
115
+
116
+ /**
117
+ * Sets dialog subtitle
118
+ * @param {string} subtitle - Subtitle text
119
+ * @returns {DialogComponent} Dialog component instance for chaining
120
+ */
121
+ setSubtitle(subtitle: string) {
122
+ options.content.setSubtitle(subtitle);
123
+ return this;
124
+ },
125
+
126
+ /**
127
+ * Gets dialog subtitle
128
+ * @returns {string} Subtitle text
129
+ */
130
+ getSubtitle() {
131
+ return options.content.getSubtitle();
132
+ },
133
+
134
+ /**
135
+ * Sets dialog content
136
+ * @param {string} content - Content HTML
137
+ * @returns {DialogComponent} Dialog component instance for chaining
138
+ */
139
+ setContent(content: string) {
140
+ options.content.setContent(content);
141
+ return this;
142
+ },
143
+
144
+ /**
145
+ * Gets dialog content
146
+ * @returns {string} Content HTML
147
+ */
148
+ getContent() {
149
+ return options.content.getContent();
150
+ },
151
+
152
+ /**
153
+ * Adds a button to the dialog footer
154
+ * @param {DialogButton} button - Button configuration
155
+ * @returns {DialogComponent} Dialog component instance for chaining
156
+ */
157
+ addButton(button: DialogButton) {
158
+ options.buttons.addButton(button);
159
+ return this;
160
+ },
161
+
162
+ /**
163
+ * Removes a button by index or text
164
+ * @param {number|string} indexOrText - Button index or text
165
+ * @returns {DialogComponent} Dialog component instance for chaining
166
+ */
167
+ removeButton(indexOrText: number | string) {
168
+ options.buttons.removeButton(indexOrText);
169
+ return this;
170
+ },
171
+
172
+ /**
173
+ * Gets all footer buttons
174
+ * @returns {DialogButton[]} Array of button configurations
175
+ */
176
+ getButtons() {
177
+ return options.buttons.getButtons();
178
+ },
179
+
180
+ /**
181
+ * Sets footer alignment
182
+ * @param {string} alignment - Footer alignment
183
+ * @returns {DialogComponent} Dialog component instance for chaining
184
+ */
185
+ setFooterAlignment(alignment: keyof typeof DIALOG_FOOTER_ALIGNMENTS | DIALOG_FOOTER_ALIGNMENTS) {
186
+ options.buttons.setFooterAlignment(alignment);
187
+ return this;
188
+ },
189
+
190
+ /**
191
+ * Sets dialog size
192
+ * @param {string} size - Size variant
193
+ * @returns {DialogComponent} Dialog component instance for chaining
194
+ */
195
+ setSize(size: keyof typeof DIALOG_SIZES | DIALOG_SIZES) {
196
+ options.size.setSize(size);
197
+ return this;
198
+ },
199
+
200
+ /**
201
+ * Adds event listener
202
+ * @param {string} event - Event name
203
+ * @param {Function} handler - Event handler
204
+ * @returns {DialogComponent} Dialog component instance for chaining
205
+ */
206
+ on(event: keyof typeof DIALOG_EVENTS | DIALOG_EVENTS, handler: (event: DialogEvent) => void) {
207
+ options.events.on(event, handler);
208
+ return this;
209
+ },
210
+
211
+ /**
212
+ * Removes event listener
213
+ * @param {string} event - Event name
214
+ * @param {Function} handler - Event handler
215
+ * @returns {DialogComponent} Dialog component instance for chaining
216
+ */
217
+ off(event: keyof typeof DIALOG_EVENTS | DIALOG_EVENTS, handler: (event: DialogEvent) => void) {
218
+ options.events.off(event, handler);
219
+ return this;
220
+ },
221
+
222
+ /**
223
+ * Gets dialog header element
224
+ * @returns {HTMLElement|null} Header element
225
+ */
226
+ getHeaderElement() {
227
+ return options.content.getHeaderElement();
228
+ },
229
+
230
+ /**
231
+ * Gets dialog content element
232
+ * @returns {HTMLElement|null} Content element
233
+ */
234
+ getContentElement() {
235
+ return options.content.getContentElement();
236
+ },
237
+
238
+ /**
239
+ * Gets dialog footer element
240
+ * @returns {HTMLElement|null} Footer element
241
+ */
242
+ getFooterElement() {
243
+ return options.content.getFooterElement();
244
+ },
245
+
246
+ /**
247
+ * Creates a confirmation dialog with Yes/No buttons
248
+ * @param {DialogConfirmOptions} options - Confirmation dialog options
249
+ * @returns {Promise<boolean>} Promise resolving to user choice (true for confirm, false for cancel)
250
+ */
251
+ confirm(options?: DialogConfirmOptions) {
252
+ if (component.confirm) {
253
+ return component.confirm(options || { message: 'Are you sure?' });
254
+ }
255
+
256
+ // Fallback if confirm feature is not available
257
+ return Promise.resolve(false);
258
+ },
259
+
260
+ /**
261
+ * Destroys the dialog and removes it from DOM
262
+ */
263
+ destroy() {
264
+ // Close the dialog first
265
+ if (this.isOpen()) {
266
+ this.close();
267
+ }
268
+
269
+ // Small delay to allow animations to complete
270
+ setTimeout(() => {
271
+ options.lifecycle.destroy();
272
+
273
+ // Remove the overlay from DOM
274
+ if (component.overlay && component.overlay.parentNode) {
275
+ component.overlay.parentNode.removeChild(component.overlay);
276
+ }
277
+ }, 150);
278
+ },
279
+
280
+ // Pass through element references
281
+ element: component.element,
282
+ overlay: component.overlay
283
+ });
@@ -0,0 +1,113 @@
1
+ // src/components/dialog/config.ts
2
+ import {
3
+ createComponentConfig,
4
+ createElementConfig
5
+ } from '../../core/config/component-config';
6
+ import { DialogConfig } from './types';
7
+ import { DIALOG_SIZES, DIALOG_ANIMATIONS, DIALOG_FOOTER_ALIGNMENTS } from './constants';
8
+
9
+ /**
10
+ * Default configuration for the Dialog component
11
+ */
12
+ export const defaultConfig: DialogConfig = {
13
+ size: DIALOG_SIZES.MEDIUM,
14
+ animation: DIALOG_ANIMATIONS.SCALE,
15
+ footerAlignment: DIALOG_FOOTER_ALIGNMENTS.RIGHT,
16
+ open: false,
17
+ closeButton: true,
18
+ closeOnOverlayClick: true,
19
+ closeOnEscape: true,
20
+ modal: true,
21
+ autofocus: true,
22
+ trapFocus: true,
23
+ headerDivider: false,
24
+ footerDivider: false,
25
+ animationDuration: 150,
26
+ buttons: []
27
+ };
28
+
29
+ /**
30
+ * Creates the base configuration for Dialog component
31
+ * @param {DialogConfig} config - User provided configuration
32
+ * @returns {DialogConfig} Complete configuration with defaults applied
33
+ */
34
+ export const createBaseConfig = (config: DialogConfig = {}): DialogConfig =>
35
+ createComponentConfig(defaultConfig, config, 'dialog') as DialogConfig;
36
+
37
+ /**
38
+ * Generates element configuration for the Dialog component
39
+ * @param {DialogConfig} config - Dialog configuration
40
+ * @returns {Object} Element configuration object for withElement
41
+ */
42
+ export const getElementConfig = (config: DialogConfig) => {
43
+ return createElementConfig(config, {
44
+ tag: 'div',
45
+ attrs: {},
46
+ className: config.class
47
+ });
48
+ };
49
+
50
+ /**
51
+ * Generates element configuration for the Dialog overlay
52
+ * @param {DialogConfig} config - Dialog configuration
53
+ * @returns {Object} Element configuration object for overlay
54
+ */
55
+ export const getOverlayConfig = (config: DialogConfig) => {
56
+ return {
57
+ tag: 'div',
58
+ attrs: {
59
+ 'aria-modal': config.modal === false ? false : true,
60
+ 'role': 'dialog',
61
+ 'tabindex': -1
62
+ },
63
+ className: ''
64
+ };
65
+ };
66
+
67
+ /**
68
+ * Creates API configuration for the Dialog component
69
+ * @param {Object} comp - Component with dialog features
70
+ * @returns {Object} API configuration object
71
+ */
72
+ export const getApiConfig = (comp) => ({
73
+ visibility: {
74
+ open: () => comp.visibility.open(),
75
+ close: () => comp.visibility.close(),
76
+ toggle: (visible?: boolean) => comp.visibility.toggle(visible),
77
+ isOpen: () => comp.visibility.isOpen()
78
+ },
79
+ content: {
80
+ setTitle: (title: string) => comp.content.setTitle(title),
81
+ getTitle: () => comp.content.getTitle(),
82
+ setSubtitle: (subtitle: string) => comp.content.setSubtitle(subtitle),
83
+ getSubtitle: () => comp.content.getSubtitle(),
84
+ setContent: (content: string) => comp.content.setContent(content),
85
+ getContent: () => comp.content.getContent(),
86
+ getHeaderElement: () => comp.content.getHeaderElement(),
87
+ getContentElement: () => comp.content.getContentElement(),
88
+ getFooterElement: () => comp.content.getFooterElement()
89
+ },
90
+ buttons: {
91
+ addButton: (button) => comp.buttons.addButton(button),
92
+ removeButton: (indexOrText) => comp.buttons.removeButton(indexOrText),
93
+ getButtons: () => comp.buttons.getButtons(),
94
+ setFooterAlignment: (alignment) => comp.buttons.setFooterAlignment(alignment)
95
+ },
96
+ focus: {
97
+ trapFocus: () => comp.focus.trapFocus(),
98
+ releaseFocus: () => comp.focus.releaseFocus()
99
+ },
100
+ size: {
101
+ setSize: (size) => comp.size.setSize(size)
102
+ },
103
+ events: {
104
+ on: (event, handler) => comp.events.on(event, handler),
105
+ off: (event, handler) => comp.events.off(event, handler),
106
+ trigger: (event, data) => comp.events.trigger(event, data)
107
+ },
108
+ lifecycle: {
109
+ destroy: () => comp.lifecycle.destroy()
110
+ }
111
+ });
112
+
113
+ export default defaultConfig;
@@ -0,0 +1,32 @@
1
+ // src/components/dialog/constants.ts
2
+
3
+ export const DIALOG_SIZES = {
4
+ SMALL: 'small',
5
+ MEDIUM: 'medium',
6
+ LARGE: 'large',
7
+ FULLWIDTH: 'fullwidth',
8
+ FULLSCREEN: 'fullscreen'
9
+ };
10
+
11
+ export const DIALOG_ANIMATIONS = {
12
+ SCALE: 'scale',
13
+ SLIDE_UP: 'slide-up',
14
+ SLIDE_DOWN: 'slide-down',
15
+ FADE: 'fade'
16
+ };
17
+
18
+ export const DIALOG_FOOTER_ALIGNMENTS = {
19
+ RIGHT: 'right',
20
+ LEFT: 'left',
21
+ CENTER: 'center',
22
+ SPACE_BETWEEN: 'space-between'
23
+ };
24
+
25
+ export const DIALOG_EVENTS = {
26
+ OPEN: 'open',
27
+ CLOSE: 'close',
28
+ BEFORE_OPEN: 'beforeopen',
29
+ BEFORE_CLOSE: 'beforeclose',
30
+ AFTER_OPEN: 'afteropen',
31
+ AFTER_CLOSE: 'afterclose'
32
+ };
@@ -0,0 +1,56 @@
1
+ // src/components/dialog/dialog.ts
2
+ import { pipe } from '../../core/compose';
3
+ import { createBase, withElement } from '../../core/compose/component';
4
+ import { withEvents, withLifecycle } from '../../core/compose/features';
5
+ import {
6
+ withStructure,
7
+ withVisibility,
8
+ withContent,
9
+ withButtons,
10
+ withSize,
11
+ withConfirm
12
+ } from './features';
13
+ import { withAPI } from './api';
14
+ import { DialogConfig, DialogComponent } from './types';
15
+ import { createBaseConfig, getElementConfig, getApiConfig } from './config';
16
+
17
+ /**
18
+ * Creates a new Dialog component
19
+ * @param {DialogConfig} config - Dialog configuration object
20
+ * @returns {DialogComponent} Dialog component instance
21
+ */
22
+ const createDialog = (config: DialogConfig = {}): DialogComponent => {
23
+ const baseConfig = createBaseConfig(config);
24
+
25
+ try {
26
+ const dialog = pipe(
27
+ createBase,
28
+ withEvents(),
29
+ withElement(getElementConfig(baseConfig)),
30
+ withStructure(baseConfig),
31
+ withVisibility(),
32
+ withContent(),
33
+ withButtons(),
34
+ withSize(),
35
+ withConfirm(),
36
+ withLifecycle(),
37
+ comp => withAPI(getApiConfig(comp))(comp)
38
+ )(baseConfig);
39
+
40
+ // Register event handlers from config
41
+ if (baseConfig.on) {
42
+ Object.entries(baseConfig.on).forEach(([event, handler]) => {
43
+ if (typeof handler === 'function') {
44
+ dialog.on(event, handler);
45
+ }
46
+ });
47
+ }
48
+
49
+ return dialog;
50
+ } catch (error) {
51
+ console.error('Dialog creation error:', error);
52
+ throw new Error(`Failed to create dialog: ${(error as Error).message}`);
53
+ }
54
+ };
55
+
56
+ export default createDialog;