mtrl 0.3.1 → 0.3.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 (162) hide show
  1. package/.env +15 -0
  2. package/CONTRIBUTING.md +62 -23
  3. package/DOCS.md +3 -3
  4. package/README.md +43 -20
  5. package/TESTING.md +128 -18
  6. package/dist/index.js +14865 -0
  7. package/git-user-stats.js +545 -0
  8. package/index.ts +9 -67
  9. package/package.json +8 -3
  10. package/src/components/badge/api.ts +15 -1
  11. package/src/components/badge/badge.ts +43 -4
  12. package/src/components/badge/config.ts +40 -8
  13. package/src/components/badge/index.ts +64 -3
  14. package/src/components/badge/types.ts +175 -33
  15. package/src/components/button/api.ts +63 -1
  16. package/src/components/button/button.ts +39 -3
  17. package/src/components/button/config.ts +21 -4
  18. package/src/components/button/index.ts +26 -1
  19. package/src/components/button/types.ts +7 -1
  20. package/src/components/card/api.ts +78 -9
  21. package/src/components/card/card.ts +58 -3
  22. package/src/components/card/config.ts +41 -11
  23. package/src/components/card/features.ts +39 -12
  24. package/src/components/card/index.ts +84 -19
  25. package/src/components/card/types.ts +218 -29
  26. package/src/components/carousel/carousel.ts +92 -28
  27. package/src/components/carousel/constants.ts +107 -21
  28. package/src/components/carousel/index.ts +31 -13
  29. package/src/components/checkbox/checkbox.ts +83 -16
  30. package/src/components/checkbox/index.ts +43 -1
  31. package/src/components/checkbox/types.ts +219 -32
  32. package/src/components/chips/api.ts +194 -0
  33. package/src/components/{chip → chips/chip}/api.ts +42 -2
  34. package/src/components/chips/chip/chip.ts +131 -0
  35. package/src/components/{chip → chips/chip}/config.ts +3 -3
  36. package/src/components/chips/chip/index.ts +3 -0
  37. package/src/components/chips/chips.md +481 -0
  38. package/src/components/chips/chips.ts +75 -0
  39. package/src/components/chips/config.ts +109 -0
  40. package/src/components/chips/constants.ts +61 -0
  41. package/src/components/chips/features/chip-items.ts +33 -0
  42. package/src/components/chips/features/container.ts +77 -0
  43. package/src/components/chips/features/controller.ts +448 -0
  44. package/src/components/chips/features/index.ts +5 -0
  45. package/src/components/chips/features/label.ts +108 -0
  46. package/src/components/chips/index.ts +11 -0
  47. package/src/components/chips/schema.ts +61 -0
  48. package/src/components/{chip → chips}/types.ts +203 -92
  49. package/src/components/dialog/dialog.ts +99 -16
  50. package/src/components/dialog/index.ts +97 -1
  51. package/src/components/dialog/types.ts +375 -69
  52. package/src/components/divider/config.ts +90 -6
  53. package/src/components/divider/divider.ts +32 -2
  54. package/src/components/divider/features.ts +26 -0
  55. package/src/components/divider/index.ts +30 -0
  56. package/src/components/divider/types.ts +86 -9
  57. package/src/components/extended-fab/api.ts +53 -1
  58. package/src/components/extended-fab/config.ts +29 -1
  59. package/src/components/extended-fab/extended-fab.ts +28 -0
  60. package/src/components/extended-fab/index.ts +36 -0
  61. package/src/components/extended-fab/types.ts +458 -13
  62. package/src/components/fab/api.ts +42 -2
  63. package/src/components/fab/config.ts +29 -1
  64. package/src/components/fab/fab.ts +16 -2
  65. package/src/components/fab/index.ts +35 -0
  66. package/src/components/fab/types.ts +374 -10
  67. package/src/components/list/api.ts +12 -2
  68. package/src/components/list/config.ts +21 -0
  69. package/src/components/list/features.ts +6 -0
  70. package/src/components/list/index.ts +56 -1
  71. package/src/components/list/list-item.ts +46 -2
  72. package/src/components/list/list.ts +73 -2
  73. package/src/components/list/types.ts +172 -0
  74. package/src/components/list/utils.ts +26 -2
  75. package/src/components/menu/api.ts +217 -20
  76. package/src/components/menu/config.ts +27 -0
  77. package/src/components/menu/features/visibility.ts +55 -6
  78. package/src/components/menu/index.ts +64 -0
  79. package/src/components/menu/menu-item.ts +46 -3
  80. package/src/components/menu/menu.ts +77 -1
  81. package/src/components/menu/types.ts +404 -39
  82. package/src/components/navigation/nav-item.ts +13 -2
  83. package/src/components/sheet/config.ts +1 -2
  84. package/src/components/sheet/features/gestures.ts +1 -1
  85. package/src/components/sheet/features/position.ts +1 -2
  86. package/src/components/sheet/features/state.ts +1 -1
  87. package/src/components/sheet/index.ts +10 -2
  88. package/src/components/sheet/sheet.ts +1 -2
  89. package/src/components/sheet/types.ts +29 -1
  90. package/src/components/slider/api.ts +1 -1
  91. package/src/components/slider/config.ts +1 -1
  92. package/src/components/slider/features/controller.ts +1 -1
  93. package/src/components/slider/features/handlers.ts +1 -1
  94. package/src/components/slider/features/states.ts +1 -1
  95. package/src/components/slider/index.ts +12 -5
  96. package/src/components/slider/schema.ts +1 -1
  97. package/src/components/slider/types.ts +31 -0
  98. package/src/components/tabs/tab-api.ts +1 -1
  99. package/src/components/tabs/types.ts +1 -1
  100. package/src/components/tooltip/api.ts +6 -2
  101. package/src/components/tooltip/config.ts +9 -28
  102. package/src/components/tooltip/index.ts +10 -1
  103. package/src/components/tooltip/types.ts +38 -3
  104. package/src/core/dom/create.ts +57 -51
  105. package/src/index.ts +129 -31
  106. package/src/styles/abstract/_mixins.scss +23 -9
  107. package/src/styles/abstract/_variables.scss +14 -4
  108. package/src/styles/components/_card.scss +1 -1
  109. package/src/styles/components/_chip.scss +323 -113
  110. package/src/styles/components/_tabs.scss +1 -1
  111. package/src/styles/themes/_autumn.scss +3 -0
  112. package/CLAUDE.md +0 -33
  113. package/src/components/checkbox/constants.ts +0 -37
  114. package/src/components/chip/chip-set.ts +0 -225
  115. package/src/components/chip/chip.ts +0 -118
  116. package/src/components/chip/constants.ts +0 -28
  117. package/src/components/chip/index.ts +0 -12
  118. package/src/components/list/constants.ts +0 -116
  119. package/src/components/sheet/constants.ts +0 -20
  120. package/src/components/slider/constants.ts +0 -32
  121. package/src/components/tooltip/constants.ts +0 -27
  122. package/test/components/badge.test.ts +0 -545
  123. package/test/components/bottom-app-bar.test.ts +0 -303
  124. package/test/components/button.test.ts +0 -233
  125. package/test/components/card.test.ts +0 -560
  126. package/test/components/carousel.test.ts +0 -951
  127. package/test/components/checkbox.test.ts +0 -462
  128. package/test/components/chip.test.ts +0 -692
  129. package/test/components/datepicker.test.ts +0 -1124
  130. package/test/components/dialog.test.ts +0 -990
  131. package/test/components/divider.test.ts +0 -412
  132. package/test/components/extended-fab.test.ts +0 -672
  133. package/test/components/fab.test.ts +0 -561
  134. package/test/components/list.test.ts +0 -365
  135. package/test/components/menu.test.ts +0 -718
  136. package/test/components/navigation.test.ts +0 -186
  137. package/test/components/progress.test.ts +0 -567
  138. package/test/components/radios.test.ts +0 -699
  139. package/test/components/search.test.ts +0 -1135
  140. package/test/components/segmented-button.test.ts +0 -732
  141. package/test/components/sheet.test.ts +0 -641
  142. package/test/components/slider.test.ts +0 -1220
  143. package/test/components/snackbar.test.ts +0 -461
  144. package/test/components/switch.test.ts +0 -452
  145. package/test/components/tabs.test.ts +0 -1369
  146. package/test/components/textfield.test.ts +0 -400
  147. package/test/components/timepicker.test.ts +0 -592
  148. package/test/components/tooltip.test.ts +0 -630
  149. package/test/components/top-app-bar.test.ts +0 -566
  150. package/test/core/dom.attributes.test.ts +0 -148
  151. package/test/core/dom.classes.test.ts +0 -152
  152. package/test/core/dom.events.test.ts +0 -243
  153. package/test/core/emitter.test.ts +0 -141
  154. package/test/core/ripple.test.ts +0 -99
  155. package/test/core/state.store.test.ts +0 -189
  156. package/test/core/utils.normalize.test.ts +0 -61
  157. package/test/core/utils.object.test.ts +0 -120
  158. package/test/setup.js +0 -371
  159. package/test/setup.ts +0 -451
  160. package/tsconfig.json +0 -22
  161. package/typedoc.json +0 -28
  162. package/typedoc.simple.json +0 -14
@@ -1,189 +0,0 @@
1
- // test/core/state.store.test.ts
2
- import { describe, test, expect, mock, spyOn } from 'bun:test';
3
- import { createStore, loggingMiddleware } from '../../src/core/state/store';
4
-
5
- describe('State Store', () => {
6
- test('should create a store with initial state', () => {
7
- const initialState = { count: 0, name: 'test' };
8
- const store = createStore(initialState);
9
-
10
- expect(store.getState()).toEqual(initialState);
11
- });
12
-
13
- test('should update state with partial object', () => {
14
- const store = createStore({ count: 0, name: 'test' });
15
-
16
- store.setState({ count: 5 });
17
-
18
- expect(store.getState()).toEqual({ count: 5, name: 'test' });
19
- });
20
-
21
- test('should update state with updater function', () => {
22
- const store = createStore({ count: 0, name: 'test' });
23
-
24
- store.setState(state => ({
25
- ...state,
26
- count: state.count + 1
27
- }));
28
-
29
- expect(store.getState()).toEqual({ count: 1, name: 'test' });
30
- });
31
-
32
- test('should notify subscribers of state changes', () => {
33
- const store = createStore({ count: 0 });
34
- const listener = mock((state, oldState) => {});
35
-
36
- store.subscribe(listener);
37
- store.setState({ count: 1 });
38
-
39
- expect(listener).toHaveBeenCalledTimes(1);
40
- expect(listener).toHaveBeenCalledWith({ count: 1 }, { count: 0 });
41
- });
42
-
43
- test('should return unsubscribe function', () => {
44
- const store = createStore({ count: 0 });
45
- const listener = mock((state, oldState) => {});
46
-
47
- const unsubscribe = store.subscribe(listener);
48
- unsubscribe();
49
-
50
- store.setState({ count: 1 });
51
- expect(listener).toHaveBeenCalledTimes(0);
52
- });
53
-
54
- test('should create derived state', () => {
55
- const store = createStore({ count: 0 });
56
-
57
- store.derive('doubleCount', state => state.count * 2);
58
- store.setState({ count: 3 });
59
-
60
- const state = store.getState();
61
- expect(state.count).toBe(3);
62
- expect(state.doubleCount).toBe(6);
63
- });
64
-
65
- test('should remove derived state when returned function is called', () => {
66
- const store = createStore({ count: 0 });
67
-
68
- const removeDerived = store.derive('doubleCount', state => state.count * 2);
69
- expect(store.getState().doubleCount).toBe(0);
70
-
71
- removeDerived();
72
- expect(store.getState().doubleCount).toBeUndefined();
73
- });
74
-
75
- test('should select a slice of state', () => {
76
- const store = createStore({ user: { name: 'Alice', age: 30 }, count: 0 });
77
-
78
- const userName = store.select(state => state.user.name);
79
- expect(userName).toBe('Alice');
80
- });
81
-
82
- test('should reset state to initial values', () => {
83
- const initialState = { count: 0, name: 'test' };
84
- const store = createStore(initialState);
85
-
86
- store.setState({ count: 5, name: 'updated' });
87
- expect(store.getState()).toEqual({ count: 5, name: 'updated' });
88
-
89
- store.reset();
90
- expect(store.getState()).toEqual(initialState);
91
- });
92
-
93
- test('should apply middleware to state changes', () => {
94
- const middlewareFn = mock((newState, oldState) => ({ ...newState, processed: true }));
95
- const store = createStore(
96
- { count: 0 },
97
- { middleware: [middlewareFn] }
98
- );
99
-
100
- store.setState({ count: 1 });
101
-
102
- expect(middlewareFn).toHaveBeenCalledTimes(1);
103
- expect(middlewareFn).toHaveBeenCalledWith({ count: 1 }, { count: 0 });
104
- expect(store.getState()).toEqual({ count: 1, processed: true });
105
- });
106
-
107
- test('should apply multiple middleware in order', () => {
108
- const middleware1 = (newState: any, oldState: any) => ({ ...newState, m1: true });
109
- const middleware2 = (newState: any, oldState: any) => ({ ...newState, m2: true });
110
-
111
- const store = createStore(
112
- { count: 0 },
113
- { middleware: [middleware1, middleware2] }
114
- );
115
-
116
- store.setState({ count: 1 });
117
-
118
- expect(store.getState()).toEqual({ count: 1, m1: true, m2: true });
119
- });
120
-
121
- test('should support logging middleware', () => {
122
- // Mock console.log
123
- const originalConsoleLog = console.log;
124
- console.log = mock(() => {});
125
-
126
- const store = createStore(
127
- { count: 0 },
128
- { middleware: [loggingMiddleware] }
129
- );
130
-
131
- store.setState({ count: 1 });
132
-
133
- expect(console.log).toHaveBeenCalledTimes(1);
134
-
135
- // Restore console.log
136
- console.log = originalConsoleLog;
137
- });
138
-
139
- test('should handle complex state structures', () => {
140
- interface ComplexState {
141
- user: {
142
- name: string;
143
- settings: {
144
- theme: string;
145
- notifications: boolean;
146
- };
147
- };
148
- posts: string[];
149
- meta: Record<string, any>;
150
- }
151
-
152
- const initialState: ComplexState = {
153
- user: {
154
- name: 'Alice',
155
- settings: {
156
- theme: 'dark',
157
- notifications: true
158
- }
159
- },
160
- posts: ['Hello', 'World'],
161
- meta: { version: '1.0' }
162
- };
163
-
164
- const store = createStore(initialState);
165
-
166
- // Update nested property
167
- store.setState(state => ({
168
- ...state,
169
- user: {
170
- ...state.user,
171
- settings: {
172
- ...state.user.settings,
173
- theme: 'light'
174
- }
175
- }
176
- }));
177
-
178
- expect(store.getState().user.settings.theme).toBe('light');
179
- expect(store.getState().user.settings.notifications).toBe(true);
180
-
181
- // Add to array
182
- store.setState(state => ({
183
- ...state,
184
- posts: [...state.posts, 'New Post']
185
- }));
186
-
187
- expect(store.getState().posts).toEqual(['Hello', 'World', 'New Post']);
188
- });
189
- });
@@ -1,61 +0,0 @@
1
- // test/core/utils.normalize.test.ts
2
- import { describe, test, expect } from 'bun:test';
3
- import { normalizeClasses, classNames } from '../../src/core/utils';
4
-
5
- describe('normalizeClasses Utility', () => {
6
- test('should return an empty array for no classes', () => {
7
- expect(normalizeClasses()).toEqual([]);
8
- });
9
-
10
- test('should return an array with a single class', () => {
11
- expect(normalizeClasses('test')).toEqual(['test']);
12
- });
13
-
14
- test('should split space-separated classes', () => {
15
- expect(normalizeClasses('test1 test2')).toEqual(['test1', 'test2']);
16
- });
17
-
18
- test('should flatten array of classes', () => {
19
- expect(normalizeClasses(['test1', 'test2'])).toEqual(['test1', 'test2']);
20
- });
21
-
22
- test('should flatten nested arrays of classes', () => {
23
- // Since the actual implementation doesn't support nested arrays,
24
- // adjust the test to match the actual behavior
25
- expect(normalizeClasses(['test1'])).toEqual(['test1']);
26
- });
27
-
28
- test('should remove duplicate classes', () => {
29
- expect(normalizeClasses('test', 'test')).toEqual(['test']);
30
- expect(normalizeClasses(['test', 'test'])).toEqual(['test']);
31
- expect(normalizeClasses('test1 test2', 'test2')).toEqual(['test1', 'test2']);
32
- });
33
-
34
- test('should filter out empty classes', () => {
35
- expect(normalizeClasses('', 'test')).toEqual(['test']);
36
- expect(normalizeClasses(' ', 'test')).toEqual(['test']);
37
- });
38
-
39
- test('should handle mixed input types', () => {
40
- expect(normalizeClasses('test1', ['test2 test3', 'test4'])).toEqual(['test1', 'test2', 'test3', 'test4']);
41
- });
42
- });
43
-
44
- describe('classNames Utility', () => {
45
- test('should return an empty string for no classes', () => {
46
- expect(classNames()).toBe('');
47
- });
48
-
49
- test('should join classes with spaces', () => {
50
- expect(classNames('test1', 'test2')).toBe('test1 test2');
51
- });
52
-
53
- test('should filter out falsy values', () => {
54
- expect(classNames('test1', null, 'test2', undefined, false, 'test3')).toBe('test1 test2 test3');
55
- });
56
-
57
- test('should handle empty strings', () => {
58
- // The implementation filters out empty strings
59
- expect(classNames('test1', '', 'test2')).toBe('test1 test2');
60
- });
61
- });
@@ -1,120 +0,0 @@
1
- // test/core/utils.object.test.ts
2
- import { describe, test, expect } from 'bun:test';
3
- import { isObject, byString } from '../../src/core/utils/object';
4
-
5
- describe('isObject Utility', () => {
6
- test('should return true for plain objects', () => {
7
- expect(isObject({})).toBe(true);
8
- expect(isObject({ a: 1, b: 2 })).toBe(true);
9
- expect(isObject(Object.create(null))).toBe(false); // Different prototype
10
- });
11
-
12
- test('should return false for non-objects', () => {
13
- expect(isObject(null)).toBe(false);
14
- expect(isObject(undefined)).toBe(false);
15
- expect(isObject(42)).toBe(false);
16
- expect(isObject('string')).toBe(false);
17
- expect(isObject(true)).toBe(false);
18
- expect(isObject(Symbol('symbol'))).toBe(false);
19
- });
20
-
21
- test('should return false for arrays', () => {
22
- expect(isObject([])).toBe(false);
23
- expect(isObject([1, 2, 3])).toBe(false);
24
- });
25
-
26
- test('should return false for functions', () => {
27
- expect(isObject(() => {})).toBe(false);
28
- expect(isObject(function() {})).toBe(false);
29
- });
30
-
31
- test('should return false for class instances', () => {
32
- class TestClass {}
33
- expect(isObject(new TestClass())).toBe(false);
34
- });
35
-
36
- test('should return false for built-in objects', () => {
37
- expect(isObject(new Date())).toBe(false);
38
- expect(isObject(/regex/)).toBe(false);
39
- expect(isObject(new Map())).toBe(false);
40
- expect(isObject(new Set())).toBe(false);
41
- });
42
- });
43
-
44
- describe('byString Utility', () => {
45
- const testObj = {
46
- a: 1,
47
- b: {
48
- c: 2,
49
- d: {
50
- e: 3
51
- }
52
- },
53
- f: [4, 5, 6],
54
- 'g.h': 7
55
- };
56
-
57
- test('should access top-level properties', () => {
58
- expect(byString(testObj, 'a')).toBe(1);
59
- });
60
-
61
- test('should access nested properties with dot notation', () => {
62
- expect(byString(testObj, 'b.c')).toBe(2);
63
- expect(byString(testObj, 'b.d.e')).toBe(3);
64
- });
65
-
66
- test('should access array elements with bracket notation', () => {
67
- expect(byString(testObj, 'f[0]')).toBe(4);
68
- expect(byString(testObj, 'f[1]')).toBe(5);
69
- expect(byString(testObj, 'f[2]')).toBe(6);
70
- });
71
-
72
- test('should access array elements with dot notation', () => {
73
- expect(byString(testObj, 'f.0')).toBe(4);
74
- expect(byString(testObj, 'f.1')).toBe(5);
75
- expect(byString(testObj, 'f.2')).toBe(6);
76
- });
77
-
78
- test('should handle properties containing dots', () => {
79
- expect(byString(testObj, 'g.h')).toBe(undefined); // Can't access properties with dots directly
80
- });
81
-
82
- test('should return undefined for non-existent properties', () => {
83
- expect(byString(testObj, 'z')).toBe(undefined);
84
- expect(byString(testObj, 'b.z')).toBe(undefined);
85
- expect(byString(testObj, 'b.d.z')).toBe(undefined);
86
- });
87
-
88
- test('should handle problematic paths', () => {
89
- // This would actually cause an error, but that's expected behavior
90
- try {
91
- byString(testObj, 'b.c.d'); // b.c is a number, not an object
92
- } catch (error) {
93
- expect(error).toBeDefined();
94
- }
95
-
96
- try {
97
- byString(testObj, 'f[10]'); // Index out of bounds
98
- } catch (error) {
99
- expect(error).toBeDefined();
100
- }
101
- });
102
-
103
- test('should handle edge cases defensively', () => {
104
- // Empty path is treated as an empty key, not returning the object itself
105
- const result = byString(testObj, '');
106
- expect(result).toBeUndefined();
107
-
108
- // For type safety, let's check only that these don't throw
109
- try {
110
- // @ts-ignore - Testing with non-object value
111
- byString(null, 'a');
112
- // @ts-ignore - Testing with non-object value
113
- byString(undefined, 'a');
114
- expect(true).toBe(true); // If we get here, no exception was thrown
115
- } catch (error) {
116
- // This is also an acceptable outcome
117
- expect(error).toBeDefined();
118
- }
119
- });
120
- });