mtrl 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demo/build.ts +349 -0
- package/demo/index.html +110 -0
- package/demo/main.js +448 -0
- package/demo/styles.css +239 -0
- package/index.ts +18 -0
- package/package.json +14 -3
- package/server.ts +86 -0
- package/src/components/badge/api.ts +70 -63
- package/src/components/badge/badge.ts +16 -2
- package/src/components/badge/config.ts +66 -13
- package/src/components/badge/features.ts +51 -42
- package/src/components/badge/index.ts +27 -2
- package/src/components/badge/types.ts +62 -30
- package/src/components/bottom-app-bar/bottom-app-bar.ts +154 -0
- package/src/components/bottom-app-bar/config.ts +29 -0
- package/src/components/bottom-app-bar/index.ts +17 -0
- package/src/components/bottom-app-bar/types.ts +114 -0
- package/src/components/button/api.ts +5 -0
- package/src/components/button/button.ts +0 -1
- package/src/components/button/config.ts +6 -2
- package/src/components/button/index.ts +10 -2
- package/src/components/button/types.ts +20 -2
- package/src/components/card/card.ts +13 -25
- package/src/components/card/config.ts +83 -30
- package/src/components/card/content.ts +8 -10
- package/src/components/card/features.ts +4 -3
- package/src/components/card/index.ts +29 -2
- package/src/components/card/types.ts +33 -22
- package/src/components/checkbox/config.ts +3 -4
- package/src/components/checkbox/index.ts +1 -2
- package/src/components/checkbox/types.ts +12 -3
- package/src/components/chip/api.ts +170 -221
- package/src/components/chip/chip.ts +34 -302
- package/src/components/chip/config.ts +1 -2
- package/src/components/chip/index.ts +10 -2
- package/src/components/chip/types.ts +224 -35
- package/src/components/datepicker/api.ts +265 -0
- package/src/components/datepicker/config.ts +141 -0
- package/src/components/datepicker/datepicker.ts +341 -0
- package/src/components/datepicker/index.ts +12 -0
- package/src/components/datepicker/render.ts +450 -0
- package/src/components/datepicker/types.ts +397 -0
- package/src/components/datepicker/utils.ts +289 -0
- package/src/components/dialog/api.ts +55 -21
- package/src/components/dialog/config.ts +12 -9
- package/src/components/dialog/dialog.ts +6 -3
- package/src/components/dialog/features.ts +345 -151
- package/src/components/dialog/index.ts +38 -8
- package/src/components/dialog/types.ts +40 -14
- package/src/components/divider/config.ts +81 -0
- package/src/components/divider/divider.ts +37 -0
- package/src/components/divider/features.ts +207 -0
- package/src/components/divider/index.ts +9 -0
- package/src/components/divider/types.ts +55 -0
- package/src/components/extended-fab/api.ts +141 -0
- package/src/components/extended-fab/config.ts +112 -0
- package/src/components/extended-fab/extended-fab.ts +125 -0
- package/src/components/extended-fab/index.ts +9 -0
- package/src/components/extended-fab/types.ts +304 -0
- package/src/components/fab/api.ts +97 -0
- package/src/components/fab/config.ts +93 -0
- package/src/components/fab/fab.ts +67 -0
- package/src/components/fab/index.ts +9 -0
- package/src/components/fab/types.ts +251 -0
- package/src/components/list/config.ts +4 -5
- package/src/components/list/features.ts +6 -7
- package/src/components/list/index.ts +7 -9
- package/src/components/list/list-item.ts +12 -13
- package/src/components/list/types.ts +50 -5
- package/src/components/list/utils.ts +30 -3
- package/src/components/menu/features/items-manager.ts +9 -9
- package/src/components/menu/features/positioning.ts +7 -7
- package/src/components/menu/features/visibility.ts +7 -7
- package/src/components/menu/index.ts +7 -9
- package/src/components/menu/menu-item.ts +6 -6
- package/src/components/menu/menu.ts +22 -0
- package/src/components/menu/types.ts +29 -10
- package/src/components/menu/utils.ts +67 -0
- package/src/components/navigation/api.ts +78 -50
- package/src/components/navigation/config.ts +22 -10
- package/src/components/navigation/features/items.ts +284 -0
- package/src/components/navigation/index.ts +0 -6
- package/src/components/navigation/nav-item.ts +70 -33
- package/src/components/navigation/navigation.ts +53 -3
- package/src/components/navigation/types.ts +117 -70
- package/src/components/progress/api.ts +2 -3
- package/src/components/progress/config.ts +2 -3
- package/src/components/progress/index.ts +0 -1
- package/src/components/progress/progress.ts +1 -2
- package/src/components/progress/types.ts +186 -33
- package/src/components/radios/config.ts +1 -1
- package/src/components/radios/index.ts +0 -1
- package/src/components/radios/types.ts +0 -7
- package/src/components/search/api.ts +203 -0
- package/src/components/search/config.ts +86 -0
- package/src/components/search/features/index.ts +4 -0
- package/src/components/search/features/search.ts +717 -0
- package/src/components/search/features/states.ts +169 -0
- package/src/components/search/features/structure.ts +197 -0
- package/src/components/search/index.ts +7 -0
- package/src/components/search/search.ts +52 -0
- package/src/components/search/types.ts +175 -0
- package/src/components/segmented-button/config.ts +80 -0
- package/src/components/segmented-button/index.ts +4 -0
- package/src/components/segmented-button/segment.ts +154 -0
- package/src/components/segmented-button/segmented-button.ts +249 -0
- package/src/components/segmented-button/types.ts +254 -0
- package/src/components/slider/accessibility.md +5 -5
- package/src/components/slider/api.ts +41 -120
- package/src/components/slider/config.ts +51 -47
- package/src/components/slider/features/handlers.ts +495 -0
- package/src/components/slider/features/index.ts +1 -2
- package/src/components/slider/features/slider.ts +66 -84
- package/src/components/slider/features/states.ts +195 -0
- package/src/components/slider/features/structure.ts +136 -206
- package/src/components/slider/features/ui.ts +145 -206
- package/src/components/slider/index.ts +2 -11
- package/src/components/slider/slider.ts +9 -12
- package/src/components/slider/types.ts +67 -26
- package/src/components/snackbar/config.ts +2 -3
- package/src/components/snackbar/constants.ts +0 -32
- package/src/components/snackbar/index.ts +0 -1
- package/src/components/snackbar/position.ts +9 -1
- package/src/components/snackbar/types.ts +122 -46
- package/src/components/switch/config.ts +2 -3
- package/src/components/switch/index.ts +0 -1
- package/src/components/switch/types.ts +3 -2
- package/src/components/tabs/config.ts +3 -4
- package/src/components/tabs/features.ts +4 -2
- package/src/components/tabs/index.ts +0 -15
- package/src/components/tabs/indicator.ts +73 -13
- package/src/components/tabs/tab-api.ts +12 -4
- package/src/components/tabs/tab.ts +18 -6
- package/src/components/tabs/types.ts +23 -5
- package/src/components/textfield/config.ts +2 -3
- package/src/components/textfield/index.ts +0 -1
- package/src/components/textfield/types.ts +17 -3
- package/src/components/timepicker/README.md +277 -0
- package/src/components/timepicker/api.ts +632 -0
- package/src/components/timepicker/clockdial.ts +482 -0
- package/src/components/timepicker/config.ts +228 -0
- package/src/components/timepicker/index.ts +3 -0
- package/src/components/timepicker/render.ts +613 -0
- package/src/components/timepicker/timepicker.ts +117 -0
- package/src/components/timepicker/types.ts +336 -0
- package/src/components/timepicker/utils.ts +241 -0
- package/src/components/tooltip/api.ts +1 -1
- package/src/components/tooltip/config.ts +27 -6
- package/src/components/tooltip/index.ts +0 -1
- package/src/components/tooltip/types.ts +13 -3
- package/src/components/top-app-bar/config.ts +83 -0
- package/src/components/top-app-bar/index.ts +11 -0
- package/src/components/top-app-bar/top-app-bar.ts +316 -0
- package/src/components/top-app-bar/types.ts +140 -0
- package/src/core/build/_ripple.scss +6 -6
- package/src/core/build/ripple.ts +72 -95
- package/src/core/compose/features/icon.ts +3 -1
- package/src/core/compose/features/ripple.ts +4 -1
- package/src/core/compose/features/textlabel.ts +23 -2
- package/src/core/dom/create.ts +5 -0
- package/src/index.ts +9 -0
- package/src/styles/abstract/_theme.scss +9 -1
- package/src/styles/components/_badge.scss +182 -0
- package/src/styles/components/_bottom-app-bar.scss +103 -0
- package/src/{components/button/_styles.scss → styles/components/_button.scss} +0 -10
- package/src/{components/checkbox/_styles.scss → styles/components/_checkbox.scss} +0 -2
- package/src/styles/components/_datepicker.scss +358 -0
- package/src/styles/components/_dialog.scss +259 -0
- package/src/styles/components/_divider.scss +57 -0
- package/src/styles/components/_extended-fab.scss +267 -0
- package/src/styles/components/_fab.scss +225 -0
- package/src/{components/navigation/_styles.scss → styles/components/_navigation.scss} +1 -0
- package/src/styles/components/_search.scss +306 -0
- package/src/styles/components/_segmented-button.scss +117 -0
- package/src/{components/slider/_styles.scss → styles/components/_slider.scss} +83 -24
- package/src/{components/switch/_styles.scss → styles/components/_switch.scss} +0 -2
- package/src/{components/tabs/_styles.scss → styles/components/_tabs.scss} +95 -33
- package/src/{components/textfield/_styles.scss → styles/components/_textfield.scss} +70 -67
- package/src/styles/components/_timepicker.scss +451 -0
- package/src/styles/components/_top-app-bar.scss +225 -0
- package/src/styles/main.scss +98 -49
- package/src/styles/themes/_autumn.scss +21 -0
- package/src/styles/themes/_base-theme.scss +61 -0
- package/src/styles/themes/_baseline.scss +58 -0
- package/src/styles/themes/_bluekhaki.scss +125 -0
- package/src/styles/themes/_brownbeige.scss +125 -0
- package/src/styles/themes/_browngreen.scss +125 -0
- package/src/styles/themes/_forest.scss +6 -0
- package/src/styles/themes/_greenbeige.scss +125 -0
- package/src/styles/themes/_material.scss +125 -0
- package/src/styles/themes/_ocean.scss +6 -0
- package/src/styles/themes/_sageivory.scss +125 -0
- package/src/styles/themes/_spring.scss +6 -0
- package/src/styles/themes/_summer.scss +5 -0
- package/src/styles/themes/_sunset.scss +5 -0
- package/src/styles/themes/_tealcaramel.scss +125 -0
- package/src/styles/themes/_winter.scss +6 -0
- package/src/components/badge/_styles.scss +0 -174
- package/src/components/badge/constants.ts +0 -30
- package/src/components/button/constants.ts +0 -11
- package/src/components/card/constants.ts +0 -84
- package/src/components/dialog/_styles.scss +0 -213
- package/src/components/dialog/constants.ts +0 -32
- package/src/components/menu/constants.ts +0 -154
- package/src/components/navigation/constants.ts +0 -200
- package/src/components/navigation/features/items.js +0 -192
- package/src/components/progress/constants.ts +0 -29
- package/src/components/slider/features/appearance.ts +0 -94
- package/src/components/slider/features/disabled.ts +0 -68
- package/src/components/slider/features/events.ts +0 -164
- package/src/components/slider/features/interactions.ts +0 -396
- package/src/components/slider/features/keyboard.ts +0 -233
- package/src/components/switch/constants.ts +0 -80
- package/src/components/tabs/constants.ts +0 -89
- package/src/core/collection/adapters/mongodb.js +0 -232
- /package/src/{components/card/_styles.scss → styles/components/_card.scss} +0 -0
- /package/src/{components/carousel/_styles.scss → styles/components/_carousel.scss} +0 -0
- /package/src/{components/chip/_styles.scss → styles/components/_chip.scss} +0 -0
- /package/src/{components/list/_styles.scss → styles/components/_list.scss} +0 -0
- /package/src/{components/menu/_styles.scss → styles/components/_menu.scss} +0 -0
- /package/src/{components/progress/_styles.scss → styles/components/_progress.scss} +0 -0
- /package/src/{components/radios/_styles.scss → styles/components/_radios.scss} +0 -0
- /package/src/{components/sheet/_styles.scss → styles/components/_sheet.scss} +0 -0
- /package/src/{components/snackbar/_styles.scss → styles/components/_snackbar.scss} +0 -0
- /package/src/{components/tooltip/_styles.scss → styles/components/_tooltip.scss} +0 -0
- /package/src/styles/utilities/{_color.scss → _colors.scss} +0 -0
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
// src/components/slider/features/keyboard.ts
|
|
2
|
-
import { SLIDER_EVENTS } from '../constants';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Add keyboard interaction handlers to slider component
|
|
6
|
-
*
|
|
7
|
-
* @param state Slider state object
|
|
8
|
-
* @param handlers Object containing handler methods
|
|
9
|
-
* @returns Event handlers for keyboard interactions
|
|
10
|
-
*/
|
|
11
|
-
export const createKeyboardHandlers = (state, handlers) => {
|
|
12
|
-
const {
|
|
13
|
-
secondThumb,
|
|
14
|
-
secondValueBubble,
|
|
15
|
-
valueBubble
|
|
16
|
-
} = state.component.structure;
|
|
17
|
-
|
|
18
|
-
const {
|
|
19
|
-
showValueBubble,
|
|
20
|
-
updateUi,
|
|
21
|
-
triggerEvent
|
|
22
|
-
} = handlers;
|
|
23
|
-
|
|
24
|
-
// Last focused thumb tracker to handle tab sequences properly
|
|
25
|
-
let lastFocusedThumb = null;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Clear any existing bubble hide timers
|
|
29
|
-
*/
|
|
30
|
-
const clearBubbleHideTimer = () => {
|
|
31
|
-
if (state.valueHideTimer) {
|
|
32
|
-
clearTimeout(state.valueHideTimer);
|
|
33
|
-
state.valueHideTimer = null;
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Hide all bubbles immediately
|
|
39
|
-
*/
|
|
40
|
-
const hideAllBubbles = () => {
|
|
41
|
-
// Clear any pending hide timers
|
|
42
|
-
clearBubbleHideTimer();
|
|
43
|
-
|
|
44
|
-
// Hide both bubbles immediately
|
|
45
|
-
if (valueBubble) {
|
|
46
|
-
showValueBubble(valueBubble, false);
|
|
47
|
-
}
|
|
48
|
-
if (secondValueBubble) {
|
|
49
|
-
showValueBubble(secondValueBubble, false);
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Shows a bubble element with consistent behavior
|
|
55
|
-
*/
|
|
56
|
-
const showBubble = (bubble) => {
|
|
57
|
-
// First hide all bubbles
|
|
58
|
-
hideAllBubbles();
|
|
59
|
-
|
|
60
|
-
// Then show the active bubble
|
|
61
|
-
if (bubble) {
|
|
62
|
-
showValueBubble(bubble, true);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Hides a bubble element with optional delay
|
|
68
|
-
*/
|
|
69
|
-
const hideBubble = (bubble, delay = 0) => {
|
|
70
|
-
// Clear any existing timers
|
|
71
|
-
clearBubbleHideTimer();
|
|
72
|
-
|
|
73
|
-
if (!bubble) return;
|
|
74
|
-
|
|
75
|
-
if (delay > 0) {
|
|
76
|
-
state.valueHideTimer = setTimeout(() => {
|
|
77
|
-
showValueBubble(bubble, false);
|
|
78
|
-
}, delay);
|
|
79
|
-
} else {
|
|
80
|
-
showValueBubble(bubble, false);
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
// Event handlers
|
|
85
|
-
const handleKeyDown = (e, isSecondThumb = false) => {
|
|
86
|
-
if (state.component.disabled && state.component.disabled.isDisabled()) return;
|
|
87
|
-
|
|
88
|
-
const step = state.step || 1;
|
|
89
|
-
let newValue;
|
|
90
|
-
let stepSize = step;
|
|
91
|
-
|
|
92
|
-
// Determine which value to modify
|
|
93
|
-
if (isSecondThumb) {
|
|
94
|
-
newValue = state.secondValue;
|
|
95
|
-
} else {
|
|
96
|
-
newValue = state.value;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Handle tab key specifically for range sliders
|
|
100
|
-
if (e.key === 'Tab') {
|
|
101
|
-
// Let the browser handle the tab navigation
|
|
102
|
-
// We'll deal with showing/hiding bubbles in the focus/blur handlers
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Determine step size based on modifier keys
|
|
107
|
-
if (e.shiftKey) {
|
|
108
|
-
stepSize = step * 10; // Large step when Shift is pressed
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
let valueChanged = false;
|
|
112
|
-
|
|
113
|
-
switch (e.key) {
|
|
114
|
-
case 'ArrowRight':
|
|
115
|
-
case 'ArrowUp':
|
|
116
|
-
e.preventDefault();
|
|
117
|
-
newValue = Math.min(newValue + stepSize, state.max);
|
|
118
|
-
valueChanged = true;
|
|
119
|
-
break;
|
|
120
|
-
|
|
121
|
-
case 'ArrowLeft':
|
|
122
|
-
case 'ArrowDown':
|
|
123
|
-
e.preventDefault();
|
|
124
|
-
newValue = Math.max(newValue - stepSize, state.min);
|
|
125
|
-
valueChanged = true;
|
|
126
|
-
break;
|
|
127
|
-
|
|
128
|
-
case 'Home':
|
|
129
|
-
e.preventDefault();
|
|
130
|
-
newValue = state.min;
|
|
131
|
-
valueChanged = true;
|
|
132
|
-
break;
|
|
133
|
-
|
|
134
|
-
case 'End':
|
|
135
|
-
e.preventDefault();
|
|
136
|
-
newValue = state.max;
|
|
137
|
-
valueChanged = true;
|
|
138
|
-
break;
|
|
139
|
-
|
|
140
|
-
case 'PageUp':
|
|
141
|
-
e.preventDefault();
|
|
142
|
-
newValue = Math.min(newValue + (step * 10), state.max);
|
|
143
|
-
valueChanged = true;
|
|
144
|
-
break;
|
|
145
|
-
|
|
146
|
-
case 'PageDown':
|
|
147
|
-
e.preventDefault();
|
|
148
|
-
newValue = Math.max(newValue - (step * 10), state.min);
|
|
149
|
-
valueChanged = true;
|
|
150
|
-
break;
|
|
151
|
-
|
|
152
|
-
default:
|
|
153
|
-
return; // Exit if not a handled key
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (!valueChanged) return;
|
|
157
|
-
|
|
158
|
-
// Update active bubble reference
|
|
159
|
-
state.activeBubble = isSecondThumb ? secondValueBubble : valueBubble;
|
|
160
|
-
|
|
161
|
-
// Show value bubble during keyboard interaction
|
|
162
|
-
showBubble(state.activeBubble);
|
|
163
|
-
|
|
164
|
-
// Update the value
|
|
165
|
-
if (isSecondThumb) {
|
|
166
|
-
state.secondValue = newValue;
|
|
167
|
-
} else {
|
|
168
|
-
state.value = newValue;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Update UI
|
|
172
|
-
updateUi();
|
|
173
|
-
|
|
174
|
-
// Trigger events
|
|
175
|
-
triggerEvent(SLIDER_EVENTS.INPUT, e);
|
|
176
|
-
triggerEvent(SLIDER_EVENTS.CHANGE, e);
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
const handleFocus = (e, isSecondThumb = false) => {
|
|
180
|
-
if (state.component.disabled && state.component.disabled.isDisabled()) return;
|
|
181
|
-
|
|
182
|
-
// Track the currently focused thumb for tab sequence handling
|
|
183
|
-
const currentThumb = isSecondThumb ? secondThumb : state.component.structure.thumb;
|
|
184
|
-
|
|
185
|
-
// If we're tabbing between thumbs, hide the previous bubble immediately
|
|
186
|
-
if (lastFocusedThumb && lastFocusedThumb !== currentThumb) {
|
|
187
|
-
hideAllBubbles();
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// Update the last focused thumb
|
|
191
|
-
lastFocusedThumb = currentThumb;
|
|
192
|
-
|
|
193
|
-
// Add a class to indicate keyboard focus
|
|
194
|
-
currentThumb.classList.add(`${state.component.getClass('slider-thumb')}--focused`);
|
|
195
|
-
|
|
196
|
-
// Show value bubble on focus
|
|
197
|
-
const bubble = isSecondThumb ? secondValueBubble : valueBubble;
|
|
198
|
-
showBubble(bubble);
|
|
199
|
-
|
|
200
|
-
// Update active bubble reference
|
|
201
|
-
state.activeBubble = bubble;
|
|
202
|
-
|
|
203
|
-
// Trigger focus event
|
|
204
|
-
triggerEvent(SLIDER_EVENTS.FOCUS, e);
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
const handleBlur = (e, isSecondThumb = false) => {
|
|
208
|
-
// Remove keyboard focus class
|
|
209
|
-
const thumb = isSecondThumb ? secondThumb : state.component.structure.thumb;
|
|
210
|
-
thumb.classList.remove(`${state.component.getClass('slider-thumb')}--focused`);
|
|
211
|
-
|
|
212
|
-
// Only hide the bubble if we're not tabbing to another thumb
|
|
213
|
-
// This check prevents the bubble from flickering when tabbing between thumbs
|
|
214
|
-
const relatedTarget = e.relatedTarget;
|
|
215
|
-
const otherThumb = isSecondThumb ? state.component.structure.thumb : secondThumb;
|
|
216
|
-
|
|
217
|
-
if (!relatedTarget || relatedTarget !== otherThumb) {
|
|
218
|
-
// We're not tabbing to the other thumb, so we can hide the bubble
|
|
219
|
-
const bubble = isSecondThumb ? secondValueBubble : valueBubble;
|
|
220
|
-
hideBubble(bubble, 200);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Trigger blur event
|
|
224
|
-
triggerEvent(SLIDER_EVENTS.BLUR, e);
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
// Return handlers
|
|
228
|
-
return {
|
|
229
|
-
handleKeyDown,
|
|
230
|
-
handleFocus,
|
|
231
|
-
handleBlur
|
|
232
|
-
};
|
|
233
|
-
};
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
// src/components/switch/constants.ts
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Label position options
|
|
5
|
-
*/
|
|
6
|
-
export const SWITCH_LABEL_POSITION = {
|
|
7
|
-
START: 'start',
|
|
8
|
-
END: 'end'
|
|
9
|
-
} as const;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Validation schema for switch configuration
|
|
13
|
-
*/
|
|
14
|
-
export const SWITCH_SCHEMA = {
|
|
15
|
-
type: 'object',
|
|
16
|
-
properties: {
|
|
17
|
-
name: {
|
|
18
|
-
type: 'string',
|
|
19
|
-
optional: true
|
|
20
|
-
},
|
|
21
|
-
checked: {
|
|
22
|
-
type: 'boolean',
|
|
23
|
-
optional: true
|
|
24
|
-
},
|
|
25
|
-
required: {
|
|
26
|
-
type: 'boolean',
|
|
27
|
-
optional: true
|
|
28
|
-
},
|
|
29
|
-
disabled: {
|
|
30
|
-
type: 'boolean',
|
|
31
|
-
optional: true
|
|
32
|
-
},
|
|
33
|
-
value: {
|
|
34
|
-
type: 'string',
|
|
35
|
-
optional: true
|
|
36
|
-
},
|
|
37
|
-
label: {
|
|
38
|
-
type: 'string',
|
|
39
|
-
optional: true
|
|
40
|
-
},
|
|
41
|
-
labelPosition: {
|
|
42
|
-
type: 'string',
|
|
43
|
-
enum: Object.values(SWITCH_LABEL_POSITION),
|
|
44
|
-
optional: true
|
|
45
|
-
},
|
|
46
|
-
icon: {
|
|
47
|
-
type: 'string',
|
|
48
|
-
optional: true
|
|
49
|
-
},
|
|
50
|
-
ariaLabel: {
|
|
51
|
-
type: 'string',
|
|
52
|
-
optional: true
|
|
53
|
-
},
|
|
54
|
-
class: {
|
|
55
|
-
type: 'string',
|
|
56
|
-
optional: true
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
} as const;
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Switch state classes
|
|
63
|
-
*/
|
|
64
|
-
export const SWITCH_STATES = {
|
|
65
|
-
CHECKED: 'checked',
|
|
66
|
-
DISABLED: 'disabled',
|
|
67
|
-
FOCUSED: 'focused'
|
|
68
|
-
} as const;
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Switch element classes
|
|
72
|
-
*/
|
|
73
|
-
export const SWITCH_CLASSES = {
|
|
74
|
-
ROOT: 'switch',
|
|
75
|
-
INPUT: 'switch-input',
|
|
76
|
-
TRACK: 'switch-track',
|
|
77
|
-
THUMB: 'thumb',
|
|
78
|
-
THUMB_ICON: 'thumb-icon',
|
|
79
|
-
LABEL: 'switch-label'
|
|
80
|
-
} as const;
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
// src/components/tabs/constants.ts
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Tab variants
|
|
5
|
-
*/
|
|
6
|
-
export const TABS_VARIANTS = {
|
|
7
|
-
/** Primary tabs (standard MD3 style) */
|
|
8
|
-
PRIMARY: 'primary',
|
|
9
|
-
/** Secondary tabs (less prominent variant) */
|
|
10
|
-
SECONDARY: 'secondary'
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Tab states
|
|
15
|
-
*/
|
|
16
|
-
export const TAB_STATES = {
|
|
17
|
-
/** Active (selected) tab state */
|
|
18
|
-
ACTIVE: 'active',
|
|
19
|
-
/** Inactive (unselected) tab state */
|
|
20
|
-
INACTIVE: 'inactive',
|
|
21
|
-
/** Disabled tab state */
|
|
22
|
-
DISABLED: 'disabled'
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Tab layout types
|
|
27
|
-
*/
|
|
28
|
-
export const TAB_LAYOUT = {
|
|
29
|
-
/** Icon-only tab layout */
|
|
30
|
-
ICON_ONLY: 'icon-only',
|
|
31
|
-
/** Text-only tab layout */
|
|
32
|
-
TEXT_ONLY: 'text-only',
|
|
33
|
-
/** Icon and text layout */
|
|
34
|
-
ICON_AND_TEXT: 'icon-and-text'
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Tab interaction states (for styling)
|
|
39
|
-
*/
|
|
40
|
-
export const TAB_INTERACTION_STATES = {
|
|
41
|
-
/** Default enabled state */
|
|
42
|
-
ENABLED: 'enabled',
|
|
43
|
-
/** Hover state */
|
|
44
|
-
HOVER: 'hover',
|
|
45
|
-
/** Focus state */
|
|
46
|
-
FOCUS: 'focus',
|
|
47
|
-
/** Pressed/active state */
|
|
48
|
-
PRESSED: 'pressed'
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Tab animation constants
|
|
53
|
-
*/
|
|
54
|
-
export const TAB_ANIMATION = {
|
|
55
|
-
/** Standard transition duration in ms */
|
|
56
|
-
TRANSITION_DURATION: 200,
|
|
57
|
-
/** Standard transition timing function */
|
|
58
|
-
TRANSITION_TIMING: 'cubic-bezier(0.4, 0, 0.2, 1)',
|
|
59
|
-
/** Ripple animation duration in ms */
|
|
60
|
-
RIPPLE_DURATION: 400
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Tab accessibility roles
|
|
65
|
-
*/
|
|
66
|
-
export const TAB_A11Y = {
|
|
67
|
-
/** Tab role */
|
|
68
|
-
TAB_ROLE: 'tab',
|
|
69
|
-
/** Tablist role */
|
|
70
|
-
TABLIST_ROLE: 'tablist',
|
|
71
|
-
/** Tabpanel role */
|
|
72
|
-
TABPANEL_ROLE: 'tabpanel'
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* MD3 tokens for tab colors
|
|
77
|
-
*/
|
|
78
|
-
export const TAB_COLORS = {
|
|
79
|
-
/** Surface color for container */
|
|
80
|
-
SURFACE: 'surface',
|
|
81
|
-
/** Primary color for active tab and indicator */
|
|
82
|
-
PRIMARY: 'primary',
|
|
83
|
-
/** On-surface color for active secondary tabs */
|
|
84
|
-
ON_SURFACE: 'on-surface',
|
|
85
|
-
/** On-surface-variant for inactive tabs */
|
|
86
|
-
ON_SURFACE_VARIANT: 'on-surface-variant',
|
|
87
|
-
/** Outline variant for divider */
|
|
88
|
-
OUTLINE_VARIANT: 'outline-variant'
|
|
89
|
-
};
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
// src/core/collection/adapters/mongodb.js
|
|
2
|
-
|
|
3
|
-
import { MongoClient, ObjectId } from 'mongodb'
|
|
4
|
-
import { OPERATORS, createBaseAdapter } from './base'
|
|
5
|
-
|
|
6
|
-
const MONGODB_OPERATORS = {
|
|
7
|
-
[OPERATORS.EQ]: '$eq',
|
|
8
|
-
[OPERATORS.NE]: '$ne',
|
|
9
|
-
[OPERATORS.GT]: '$gt',
|
|
10
|
-
[OPERATORS.GTE]: '$gte',
|
|
11
|
-
[OPERATORS.LT]: '$lt',
|
|
12
|
-
[OPERATORS.LTE]: '$lte',
|
|
13
|
-
[OPERATORS.IN]: '$in',
|
|
14
|
-
[OPERATORS.NIN]: '$nin',
|
|
15
|
-
[OPERATORS.CONTAINS]: '$regex',
|
|
16
|
-
[OPERATORS.STARTS_WITH]: '$regex',
|
|
17
|
-
[OPERATORS.ENDS_WITH]: '$regex'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const createMongoAdapter = (config = {}) => {
|
|
21
|
-
const base = createBaseAdapter(config)
|
|
22
|
-
let client = null
|
|
23
|
-
let db = null
|
|
24
|
-
let collection = null
|
|
25
|
-
|
|
26
|
-
const transformDocument = (doc) => {
|
|
27
|
-
if (!doc) return null
|
|
28
|
-
const { _id, ...rest } = doc
|
|
29
|
-
return { id: _id.toString(), ...rest }
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const transformForMongo = (doc) => {
|
|
33
|
-
if (!doc) return null
|
|
34
|
-
const { id, ...rest } = doc
|
|
35
|
-
return { _id: id ? new ObjectId(id) : new ObjectId(), ...rest }
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const transformQuery = (query) => {
|
|
39
|
-
const transformed = {}
|
|
40
|
-
|
|
41
|
-
Object.entries(query).forEach(([field, conditions]) => {
|
|
42
|
-
if (typeof conditions === 'object') {
|
|
43
|
-
transformed[field] = Object.entries(conditions).reduce((acc, [op, value]) => {
|
|
44
|
-
const mongoOp = MONGODB_OPERATORS[op]
|
|
45
|
-
if (!mongoOp) return acc
|
|
46
|
-
|
|
47
|
-
if (op === OPERATORS.CONTAINS) {
|
|
48
|
-
acc[mongoOp] = new RegExp(value, 'i')
|
|
49
|
-
} else if (op === OPERATORS.STARTS_WITH) {
|
|
50
|
-
acc[mongoOp] = new RegExp(`^${value}`, 'i')
|
|
51
|
-
} else if (op === OPERATORS.ENDS_WITH) {
|
|
52
|
-
acc[mongoOp] = new RegExp(`${value}$`, 'i')
|
|
53
|
-
} else {
|
|
54
|
-
acc[mongoOp] = value
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return acc
|
|
58
|
-
}, {})
|
|
59
|
-
} else {
|
|
60
|
-
transformed[field] = conditions
|
|
61
|
-
}
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
return transformed
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
...base,
|
|
69
|
-
|
|
70
|
-
connect: async () => {
|
|
71
|
-
try {
|
|
72
|
-
client = new MongoClient(config.uri, {
|
|
73
|
-
useUnifiedTopology: true,
|
|
74
|
-
maxPoolSize: 10,
|
|
75
|
-
...config.options
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
await client.connect()
|
|
79
|
-
db = client.db(config.dbName)
|
|
80
|
-
collection = db.collection(config.collection)
|
|
81
|
-
|
|
82
|
-
// Optional: Create indexes
|
|
83
|
-
// await collection.createIndex({ field: 1 })
|
|
84
|
-
} catch (error) {
|
|
85
|
-
return base.handleError(new Error(`MongoDB connection failed: ${error.message}`))
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
disconnect: async () => {
|
|
90
|
-
if (client) {
|
|
91
|
-
await client.close()
|
|
92
|
-
client = null
|
|
93
|
-
db = null
|
|
94
|
-
collection = null
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
create: async (items) => {
|
|
99
|
-
if (!collection) {
|
|
100
|
-
return base.handleError(new Error('Not connected to MongoDB'))
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const docs = items.map(item => transformForMongo(item))
|
|
104
|
-
const result = await collection.insertMany(docs)
|
|
105
|
-
|
|
106
|
-
return items.map((item, index) => ({
|
|
107
|
-
...item,
|
|
108
|
-
id: result.insertedIds[index].toString()
|
|
109
|
-
}))
|
|
110
|
-
},
|
|
111
|
-
|
|
112
|
-
read: async (query = {}, options = {}) => {
|
|
113
|
-
if (!collection) {
|
|
114
|
-
return base.handleError(new Error('Not connected to MongoDB'))
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const {
|
|
118
|
-
skip = 0,
|
|
119
|
-
limit = 0,
|
|
120
|
-
sort = {},
|
|
121
|
-
projection = {}
|
|
122
|
-
} = options
|
|
123
|
-
|
|
124
|
-
const mongoQuery = transformQuery(query)
|
|
125
|
-
|
|
126
|
-
const cursor = collection
|
|
127
|
-
.find(mongoQuery)
|
|
128
|
-
.skip(skip)
|
|
129
|
-
.limit(limit)
|
|
130
|
-
.project(projection)
|
|
131
|
-
.sort(sort)
|
|
132
|
-
|
|
133
|
-
const docs = await cursor.toArray()
|
|
134
|
-
return docs.map(doc => transformDocument(doc))
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
update: async (items) => {
|
|
138
|
-
if (!collection) {
|
|
139
|
-
return base.handleError(new Error('Not connected to MongoDB'))
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const operations = items.map(item => ({
|
|
143
|
-
updateOne: {
|
|
144
|
-
filter: { _id: new ObjectId(item.id) },
|
|
145
|
-
update: { $set: transformForMongo(item) },
|
|
146
|
-
upsert: false
|
|
147
|
-
}
|
|
148
|
-
}))
|
|
149
|
-
|
|
150
|
-
await collection.bulkWrite(operations)
|
|
151
|
-
return items
|
|
152
|
-
},
|
|
153
|
-
|
|
154
|
-
delete: async (ids) => {
|
|
155
|
-
if (!collection) {
|
|
156
|
-
return base.handleError(new Error('Not connected to MongoDB'))
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const mongoIds = ids.map(id => new ObjectId(id))
|
|
160
|
-
await collection.deleteMany({ _id: { $in: mongoIds } })
|
|
161
|
-
return ids
|
|
162
|
-
},
|
|
163
|
-
|
|
164
|
-
query: async (query = {}, options = {}) => {
|
|
165
|
-
if (!collection) {
|
|
166
|
-
return base.handleError(new Error('Not connected to MongoDB'))
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const {
|
|
170
|
-
pipeline = [],
|
|
171
|
-
skip = 0,
|
|
172
|
-
limit = 0
|
|
173
|
-
} = options
|
|
174
|
-
|
|
175
|
-
const mongoQuery = transformQuery(query)
|
|
176
|
-
|
|
177
|
-
const aggregation = [
|
|
178
|
-
{ $match: mongoQuery },
|
|
179
|
-
...pipeline
|
|
180
|
-
]
|
|
181
|
-
|
|
182
|
-
if (skip > 0) {
|
|
183
|
-
aggregation.push({ $skip: skip })
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (limit > 0) {
|
|
187
|
-
aggregation.push({ $limit: limit })
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const docs = await collection.aggregate(aggregation).toArray()
|
|
191
|
-
|
|
192
|
-
return {
|
|
193
|
-
results: docs.map(doc => transformDocument(doc)),
|
|
194
|
-
total: await collection.countDocuments(mongoQuery)
|
|
195
|
-
}
|
|
196
|
-
},
|
|
197
|
-
|
|
198
|
-
watch: (callback, pipeline = []) => {
|
|
199
|
-
if (!collection) {
|
|
200
|
-
return base.handleError(new Error('Not connected to MongoDB'))
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const changeStream = collection.watch(pipeline, {
|
|
204
|
-
fullDocument: 'updateLookup'
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
changeStream.on('change', async (change) => {
|
|
208
|
-
const { operationType, documentKey, fullDocument } = change
|
|
209
|
-
|
|
210
|
-
switch (operationType) {
|
|
211
|
-
case 'insert':
|
|
212
|
-
case 'update':
|
|
213
|
-
case 'replace':
|
|
214
|
-
callback({
|
|
215
|
-
type: operationType,
|
|
216
|
-
document: transformDocument(fullDocument)
|
|
217
|
-
})
|
|
218
|
-
break
|
|
219
|
-
|
|
220
|
-
case 'delete':
|
|
221
|
-
callback({
|
|
222
|
-
type: operationType,
|
|
223
|
-
documentId: documentKey._id.toString()
|
|
224
|
-
})
|
|
225
|
-
break
|
|
226
|
-
}
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
return () => changeStream.close()
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|