@umbra.ui/core 0.1.18 → 0.1.19

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 (146) hide show
  1. package/dist/components/controls/Button/Button.vue +417 -0
  2. package/dist/components/controls/Button/README.md +348 -0
  3. package/dist/components/controls/Button/theme.css +200 -0
  4. package/dist/components/controls/Checkbox/Checkbox.vue +164 -0
  5. package/dist/components/controls/Checkbox/README.md +441 -0
  6. package/dist/components/controls/Checkbox/theme.css +36 -0
  7. package/dist/components/controls/Dropdown/Dropdown.vue +476 -0
  8. package/dist/components/controls/Dropdown/README.md +370 -0
  9. package/dist/components/controls/Dropdown/theme.css +50 -0
  10. package/dist/components/controls/Dropdown/types.ts +6 -0
  11. package/dist/components/controls/IconButton/IconButton.vue +267 -0
  12. package/dist/components/controls/IconButton/README.md +502 -0
  13. package/dist/components/controls/IconButton/theme.css +89 -0
  14. package/dist/components/controls/Radio/README.md +591 -0
  15. package/dist/components/controls/Radio/Radio.vue +89 -0
  16. package/dist/components/controls/Radio/theme.css +14 -0
  17. package/dist/components/controls/RangeSlider/README.md +608 -0
  18. package/dist/components/controls/RangeSlider/RangeSlider.vue +535 -0
  19. package/dist/components/controls/RangeSlider/theme.css +80 -0
  20. package/dist/components/controls/SegmentedControl/README.md +587 -0
  21. package/dist/components/controls/SegmentedControl/SegmentedControl.vue +284 -0
  22. package/dist/components/controls/SegmentedControl/theme.css +60 -0
  23. package/dist/components/controls/SegmentedControl/types.ts +5 -0
  24. package/dist/components/controls/Slider/README.md +627 -0
  25. package/dist/components/controls/Slider/Slider.vue +260 -0
  26. package/dist/components/controls/Slider/theme.css +74 -0
  27. package/dist/components/controls/Stepper/README.md +601 -0
  28. package/dist/components/controls/Stepper/Stepper.vue +103 -0
  29. package/dist/components/controls/Stepper/theme.css +53 -0
  30. package/dist/components/controls/Switch/README.md +667 -0
  31. package/dist/components/controls/Switch/Switch.vue +127 -0
  32. package/dist/components/controls/Switch/theme.css +42 -0
  33. package/dist/components/dialogs/Alert/Alert.vue +218 -0
  34. package/dist/components/dialogs/Alert/README.md +450 -0
  35. package/dist/components/dialogs/Alert/theme.css +44 -0
  36. package/dist/components/dialogs/Alert/types.ts +11 -0
  37. package/dist/components/dialogs/Toast/README.md +522 -0
  38. package/dist/components/dialogs/Toast/Toast.vue +296 -0
  39. package/dist/components/dialogs/Toast/ToastContainer.vue +330 -0
  40. package/dist/components/dialogs/Toast/theme.css +44 -0
  41. package/dist/components/dialogs/Toast/types.ts +46 -0
  42. package/dist/components/dialogs/Toast/useToast.ts +127 -0
  43. package/dist/components/indicators/ProgressBar/ProgressBar.vue +98 -0
  44. package/dist/components/indicators/ProgressBar/README.md +744 -0
  45. package/dist/components/indicators/ProgressBar/theme.css +36 -0
  46. package/dist/components/indicators/Tooltip/README.md +723 -0
  47. package/dist/components/indicators/Tooltip/TooltipProvider.vue +142 -0
  48. package/dist/components/indicators/Tooltip/theme.css +18 -0
  49. package/dist/components/indicators/Tooltip/tooltip.ts +48 -0
  50. package/dist/components/indicators/Tooltip/types.ts +15 -0
  51. package/dist/components/indicators/Tooltip/useTooltip.ts +71 -0
  52. package/dist/components/inputs/AutogrowTextView/AutogrowTextView.vue +110 -0
  53. package/dist/components/inputs/AutogrowTextView/README.md +643 -0
  54. package/dist/components/inputs/AutogrowTextView/theme.css +28 -0
  55. package/dist/components/inputs/InputCard/InputCard.vue +600 -0
  56. package/dist/components/inputs/InputCard/README.md +636 -0
  57. package/dist/components/inputs/InputEmail/InputEmail.vue +698 -0
  58. package/dist/components/inputs/InputEmail/README.md +764 -0
  59. package/dist/components/inputs/InputNumber/InputNumber.vue +300 -0
  60. package/dist/components/inputs/InputNumber/README.md +749 -0
  61. package/dist/components/inputs/InputPhone/InputPhone.vue +645 -0
  62. package/dist/components/inputs/InputPhone/README.md +636 -0
  63. package/dist/components/inputs/InputSecure/InputSecure.vue +646 -0
  64. package/dist/components/inputs/InputSecure/README.md +771 -0
  65. package/dist/components/inputs/InputText/InputText.vue +225 -0
  66. package/dist/components/inputs/InputText/README.md +844 -0
  67. package/dist/components/inputs/OTP/OTP.vue +349 -0
  68. package/dist/components/inputs/OTP/README.md +736 -0
  69. package/dist/components/inputs/OTP/theme.css +50 -0
  70. package/dist/components/inputs/StringCapture/README.md +718 -0
  71. package/dist/components/inputs/StringCapture/StringCapture.vue +315 -0
  72. package/dist/components/inputs/StringCapture/theme.css +86 -0
  73. package/dist/components/inputs/Tags/README.md +897 -0
  74. package/dist/components/inputs/Tags/TagBar.vue +793 -0
  75. package/dist/components/inputs/Tags/TagCreation.vue +219 -0
  76. package/dist/components/inputs/Tags/TagPicker.vue +380 -0
  77. package/dist/components/inputs/Tags/tag-bar-styles.ts +354 -0
  78. package/dist/components/inputs/Tags/theme.css +121 -0
  79. package/dist/components/inputs/Tags/types.ts +346 -0
  80. package/dist/components/inputs/search/README.md +759 -0
  81. package/dist/components/inputs/search/SearchBar.vue +394 -0
  82. package/dist/components/inputs/search/SearchResults.vue +310 -0
  83. package/dist/components/inputs/search/theme.css +187 -0
  84. package/dist/components/inputs/search/types.ts +8 -0
  85. package/dist/components/inputs/theme.css +102 -0
  86. package/dist/components/menus/ActionMenu/ActionMenu.vue +383 -0
  87. package/dist/components/menus/ActionMenu/README.md +825 -0
  88. package/dist/components/menus/ActionMenu/theme.css +93 -0
  89. package/dist/components/models/Popover/Popover.vue +551 -0
  90. package/dist/components/models/Popover/README.md +885 -0
  91. package/dist/components/models/Popover/theme.css +52 -0
  92. package/dist/components/models/Sheet/README.md +1159 -0
  93. package/dist/components/models/Sheet/Sheet.vue +465 -0
  94. package/dist/components/models/Sheet/theme.css +72 -0
  95. package/dist/components/models/Sidebar/README.md +1228 -0
  96. package/dist/components/models/Sidebar/Sidebar.vue +480 -0
  97. package/dist/components/models/Sidebar/theme.css +90 -0
  98. package/dist/components/navigation/adaptive/AdaptiveLayout.vue +779 -0
  99. package/dist/components/navigation/adaptive/AdaptiveLayoutBreadcrumbs.vue +192 -0
  100. package/dist/components/navigation/adaptive/AdaptiveLayoutMenuButton.vue +149 -0
  101. package/dist/components/navigation/adaptive/README.md +768 -0
  102. package/dist/components/navigation/adaptive/types.ts +19 -0
  103. package/dist/components/navigation/adaptive/useAdaptiveLayout.ts +89 -0
  104. package/dist/components/navigation/adaptive/useBreakpoints.ts +41 -0
  105. package/dist/components/navigation/adaptive/useContainerMonitor.ts +214 -0
  106. package/dist/components/navigation/adaptive/useViewAnimation.ts +721 -0
  107. package/dist/components/navigation/adaptive/useViewResize.ts +211 -0
  108. package/dist/components/navigation/navstack/NavigationStack.vue +180 -0
  109. package/dist/components/navigation/navstack/README.md +994 -0
  110. package/dist/components/navigation/navstack/useNavigationStack.ts +164 -0
  111. package/dist/components/navigation/slideover/README.md +1275 -0
  112. package/dist/components/navigation/slideover/SlideoverController.vue +287 -0
  113. package/dist/components/navigation/slideover/useSlideoverController.ts +320 -0
  114. package/dist/components/navigation/splitview/README.md +1115 -0
  115. package/dist/components/navigation/splitview/SplitViewController.vue +176 -0
  116. package/dist/components/navigation/splitview/useSplitViewController.ts +388 -0
  117. package/dist/components/navigation/tabcontroller/README.md +919 -0
  118. package/dist/components/navigation/tabcontroller/TabController.vue +307 -0
  119. package/dist/components/navigation/tabcontroller/TabItem.vue +57 -0
  120. package/dist/components/navigation/tabcontroller/types.ts +24 -0
  121. package/dist/components/navigation/tabcontroller/useTabController.ts +18 -0
  122. package/dist/components/navigation/theme.css +91 -0
  123. package/dist/components/navigation/types.ts +7 -0
  124. package/dist/components/pickers/CollectionPicker/CollectionPicker.vue +398 -0
  125. package/dist/components/pickers/CollectionPicker/README.md +1115 -0
  126. package/dist/components/pickers/CollectionPicker/theme.css +14 -0
  127. package/dist/components/pickers/CollectionPicker/types.ts +11 -0
  128. package/dist/components/pickers/ColorPicker/ColorPicker.vue +376 -0
  129. package/dist/components/pickers/ColorPicker/README.md +1439 -0
  130. package/dist/components/pickers/ColorPicker/colors.ts +299 -0
  131. package/dist/components/pickers/ColorPicker/theme.css +32 -0
  132. package/dist/components/pickers/DatePicker/DatePicker.vue +660 -0
  133. package/dist/components/pickers/DatePicker/README.md +1195 -0
  134. package/dist/components/pickers/DatePicker/theme.css +22 -0
  135. package/dist/components/pickers/FilePicker/FilePicker.vue +534 -0
  136. package/dist/components/pickers/FilePicker/README.md +1542 -0
  137. package/dist/components/pickers/FilePicker/theme.css +48 -0
  138. package/dist/components/pickers/FilePicker/types.ts +10 -0
  139. package/dist/components/pickers/IconPicker/IconPicker.vue +327 -0
  140. package/dist/components/pickers/IconPicker/README.md +1161 -0
  141. package/dist/components/pickers/IconPicker/theme.css +28 -0
  142. package/dist/components/pickers/theme.css +82 -0
  143. package/dist/components/views/MarkdownViewer/MarkdownViewer.vue +442 -0
  144. package/dist/components/views/MarkdownViewer/README.md +833 -0
  145. package/dist/components/views/MarkdownViewer/theme.css +130 -0
  146. package/package.json +3 -2
@@ -0,0 +1,284 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ onMounted,
4
+ onBeforeUnmount,
5
+ ref,
6
+ computed,
7
+ watch,
8
+ nextTick,
9
+ } from "vue";
10
+ import type { ControlItem } from "./types";
11
+ import "./theme.css";
12
+
13
+ export interface Props {
14
+ items: ControlItem[];
15
+ selectedIndex?: number;
16
+ }
17
+
18
+ const props = withDefaults(defineProps<Props>(), {
19
+ items: () => [{ title: "One" }, { title: "Two" }, { title: "Three" }],
20
+ selectedIndex: 0,
21
+ });
22
+
23
+ const emit = defineEmits<{
24
+ "update:selectedIndex": [index: number];
25
+ click: [index: number, item: ControlItem];
26
+ }>();
27
+
28
+ const selectedItem = computed(() => {
29
+ const index = props.selectedIndex;
30
+ if (index >= 0 && index < props.items.length) {
31
+ return props.items[index];
32
+ }
33
+ return props.items[0];
34
+ });
35
+
36
+ // Watch for changes to the selected index
37
+ watch(
38
+ () => props.selectedIndex,
39
+ () => {
40
+ // Reposition the selected item after updating
41
+ nextTick(() => {
42
+ positionSelectedItem(true);
43
+ });
44
+ }
45
+ );
46
+
47
+ const selectedItemRef = ref<HTMLElement | null>(null);
48
+ const itemRefs = ref<(HTMLElement | null)[]>([]);
49
+
50
+ const isSelected = (title: string) => {
51
+ return selectedItem.value.title === title;
52
+ };
53
+
54
+ const updateSelectedItemWidth = () => {
55
+ if (selectedItemRef.value && itemRefs.value[0]) {
56
+ const selectedItemElement = selectedItemRef.value;
57
+ const selectedItemIndex = props.items.findIndex(
58
+ (item) => item.title === selectedItem.value.title
59
+ );
60
+ const selectedItemElementWidth =
61
+ itemRefs.value[selectedItemIndex]?.offsetWidth;
62
+
63
+ if (selectedItemElementWidth) {
64
+ // Get the computed border width
65
+ const menuElement = selectedItemElement.parentElement!;
66
+ const computedStyle = window.getComputedStyle(menuElement);
67
+ const borderRightWidth = parseFloat(computedStyle.borderRightWidth) || 0;
68
+
69
+ // Add border width to the selected item width if it's the last item
70
+ const isLastItem = selectedItemIndex === props.items.length - 1;
71
+ const additionalWidth = isLastItem ? borderRightWidth : 0;
72
+
73
+ selectedItemElement.style.width = `${
74
+ selectedItemElementWidth + additionalWidth
75
+ }px`;
76
+ }
77
+ }
78
+ };
79
+
80
+ const positionSelectedItem = (animate: boolean = true) => {
81
+ const selectedItemElement = selectedItemRef.value;
82
+ if (!selectedItemElement) return;
83
+
84
+ const selectedItemIndex = props.items.findIndex(
85
+ (item) => item.title === selectedItem.value.title
86
+ );
87
+ const targetElement = itemRefs.value[selectedItemIndex];
88
+
89
+ if (targetElement) {
90
+ const targetRect = targetElement.getBoundingClientRect();
91
+ const menuRect = selectedItemElement.parentElement!.getBoundingClientRect();
92
+
93
+ // Get the computed border width to account for borders
94
+ const menuElement = selectedItemElement.parentElement!;
95
+ const computedStyle = window.getComputedStyle(menuElement);
96
+ const borderLeftWidth = parseFloat(computedStyle.borderLeftWidth) || 0;
97
+ const borderRightWidth = parseFloat(computedStyle.borderRightWidth) || 0;
98
+
99
+ const translateX = targetRect.left - menuRect.left - borderLeftWidth;
100
+
101
+ // Temporarily disable transitions if not animating
102
+ if (!animate) {
103
+ selectedItemElement.style.transition = "none";
104
+ }
105
+
106
+ selectedItemElement.style.transform = `translateX(${translateX}px)`;
107
+
108
+ // Re-enable transitions after a frame if we disabled them
109
+ if (!animate) {
110
+ requestAnimationFrame(() => {
111
+ selectedItemElement.style.transition = "";
112
+ });
113
+ }
114
+
115
+ // Update width with border consideration
116
+ const isLastItem = selectedItemIndex === props.items.length - 1;
117
+ const additionalWidth = isLastItem ? borderRightWidth : 0;
118
+ selectedItemElement.style.width = `${
119
+ targetElement.offsetWidth + additionalWidth
120
+ }px`;
121
+ }
122
+ };
123
+
124
+ const onClick = (item: ControlItem, index: number, event: MouseEvent) => {
125
+ const clickedElement = event.currentTarget as HTMLElement;
126
+ const selectedItemElement = selectedItemRef.value;
127
+
128
+ if (selectedItemElement && clickedElement) {
129
+ const clickedRect = clickedElement.getBoundingClientRect();
130
+ const menuRect = selectedItemElement.parentElement!.getBoundingClientRect();
131
+
132
+ // Get the computed border width to account for borders
133
+ const menuElement = selectedItemElement.parentElement!;
134
+ const computedStyle = window.getComputedStyle(menuElement);
135
+ const borderLeftWidth = parseFloat(computedStyle.borderLeftWidth) || 0;
136
+ const borderRightWidth = parseFloat(computedStyle.borderRightWidth) || 0;
137
+
138
+ const translateX = clickedRect.left - menuRect.left - borderLeftWidth;
139
+
140
+ selectedItemElement.style.transform = `translateX(${translateX}px)`;
141
+
142
+ // Update width with border consideration for last item
143
+ const isLastItem = index === props.items.length - 1;
144
+ const additionalWidth = isLastItem ? borderRightWidth : 0;
145
+ selectedItemElement.style.width = `${
146
+ clickedElement.offsetWidth + additionalWidth
147
+ }px`;
148
+
149
+ // Emit the update event for two-way binding
150
+ emit("update:selectedIndex", index);
151
+ emit("click", index, item);
152
+ }
153
+ };
154
+
155
+ onMounted(() => {
156
+ // Position the selected item without animation
157
+ positionSelectedItem(false);
158
+
159
+ window.addEventListener("resize", updateSelectedItemWidth);
160
+ });
161
+
162
+ onBeforeUnmount(() => {
163
+ window.removeEventListener("resize", updateSelectedItemWidth);
164
+ });
165
+ </script>
166
+
167
+ <template>
168
+ <div :class="$style.menu">
169
+ <div :class="$style.selected" ref="selectedItemRef"></div>
170
+ <div
171
+ v-for="(item, index) in items"
172
+ :key="`toggle-item-${item.title}`"
173
+ :class="$style.item"
174
+ ref="itemRefs"
175
+ @click="onClick(item, index, $event)"
176
+ >
177
+ <p
178
+ :class="[
179
+ 'subheadline',
180
+ isSelected(item.title) ? $style.selected_title : $style.item_title,
181
+ ]"
182
+ >
183
+ {{ item.title }}
184
+ </p>
185
+ </div>
186
+ </div>
187
+ </template>
188
+
189
+ <style module>
190
+ .menu {
191
+ position: relative;
192
+ text-align: center;
193
+ cursor: default;
194
+ user-select: none;
195
+ display: flex;
196
+ align-items: center;
197
+ justify-content: space-evenly;
198
+ gap: 0;
199
+ overflow: hidden;
200
+ background-color: var(--segmentedcontrol-bg);
201
+ border-radius: var(--segmentedcontrol-border-radius);
202
+ box-shadow: var(--segmentedcontrol-box-shadow);
203
+ border: var(--segmentedcontrol-border);
204
+ flex-shrink: 0;
205
+ width: fit-content;
206
+ }
207
+
208
+ .item {
209
+ flex-grow: 1;
210
+ text-align: center;
211
+ padding-top: 0.588rem;
212
+ padding-bottom: 0.588rem;
213
+ padding-left: 1.176rem;
214
+ padding-right: 1.176rem;
215
+ min-width: fit-content;
216
+ transition: 0.2s ease-in-out background-color;
217
+ position: relative; /* Create stacking context */
218
+ border-radius: var(--segmentedcontrol-border-radius);
219
+ }
220
+ .item:hover {
221
+ background-color: var(--segmentedcontrol-hover-bg);
222
+ }
223
+
224
+ .item p {
225
+ transition: 0.3s ease-in-out opacity, 0.3s ease-in-out color;
226
+ position: relative; /* Ensure text is above background */
227
+ }
228
+ .item_title {
229
+ color: var(--segmentedcontrol-text-color);
230
+ }
231
+
232
+ .selected {
233
+ padding: 0.588rem;
234
+ text-align: center;
235
+ cursor: default;
236
+ user-select: none;
237
+ position: absolute;
238
+ top: 0;
239
+ left: 0;
240
+ bottom: 0;
241
+ width: 0;
242
+ transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1),
243
+ width 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275),
244
+ background-color 0.3s ease-in-out, color 0.3s ease-in-out;
245
+ transform-origin: center;
246
+ pointer-events: none;
247
+ background-color: var(--segmentedcontrol-selected-bg);
248
+ border-radius: var(--segmentedcontrol-selected-border-radius);
249
+ box-shadow: var(--segmentedcontrol-box-shadow);
250
+ border: var(--segmentedcontrol-selected-border);
251
+ }
252
+
253
+ .selected_title {
254
+ font-weight: 900;
255
+ font-variation-settings: "wght" 600;
256
+ color: var(--segmentedcontrol-selected-text-color);
257
+ }
258
+
259
+ .item:has(.selected_title):hover {
260
+ background-color: var(--segmentedcontrol-selected-hover-bg);
261
+ }
262
+
263
+ /* Override typography classes within this component */
264
+ .item_title:global(.subheadline) {
265
+ color: var(--segmentedcontrol-text-color);
266
+ }
267
+
268
+ .selected_title:global(.subheadline) {
269
+ font-weight: 900;
270
+ font-variation-settings: "wght" 600;
271
+ color: var(--segmentedcontrol-selected-text-color);
272
+ }
273
+
274
+ /* Fallback: Use !important with CSS custom properties if :global() doesn't work */
275
+ .item_title {
276
+ color: var(--segmentedcontrol-text-color) !important;
277
+ }
278
+
279
+ .selected_title {
280
+ font-weight: 900 !important;
281
+ font-variation-settings: "wght" 600 !important;
282
+ color: var(--segmentedcontrol-selected-text-color) !important;
283
+ }
284
+ </style>
@@ -0,0 +1,60 @@
1
+ /* Light theme using Colors */
2
+ :root {
3
+ /* SegmentedControl colors - using secondary + default values */
4
+ --segmentedcontrol-bg: #f0f0f0; /* gray5 - light background for light mode */
5
+ --segmentedcontrol-selected-bg: white; /* gray9 - muted selected for light mode */
6
+ --segmentedcontrol-text-color: #60646c; /* gray11 - muted text for light mode */
7
+ --segmentedcontrol-selected-text-color: #646464; /* white for selected text */
8
+ --segmentedcontrol-hover-bg: rgba(
9
+ 0,
10
+ 0,
11
+ 0,
12
+ 0.04
13
+ ); /* blackA2 - subtle hover for light mode */
14
+ --segmentedcontrol-selected-hover-bg: white;
15
+ --segmentedcontrol-border: 1px solid #d9d9d9;
16
+ --segmentedcontrol-border-radius: 0.353rem;
17
+ --segmentedcontrol-selected-border-radius: 0.353rem;
18
+ --segmentedcontrol-selected-border: 1px solid white;
19
+ --segmentedcontrol-shadow-dark: transparent;
20
+ --segmentedcontrol-shadow-light: transparent;
21
+ --segmentedcontrol-box-shadow: 0px 1px 0px 0px
22
+ var(--segmentedcontrol-shadow-dark),
23
+ inset 0px 1px 0px 0px var(--segmentedcontrol-shadow-light);
24
+ }
25
+
26
+ /* Dark theme */
27
+ .dark,
28
+ .dark-theme {
29
+ /* SegmentedControl colors - using secondary + default values for dark mode */
30
+ --segmentedcontrol-bg: #484848; /* Original dark mode secondary value */
31
+ --segmentedcontrol-selected-bg: #6e6e6e; /* Original dark mode secondary value */
32
+ --segmentedcontrol-text-color: #eeeeee; /* Original dark mode secondary value */
33
+ --segmentedcontrol-selected-text-color: #ffffff; /* white for selected text */
34
+ --segmentedcontrol-hover-bg: rgba(
35
+ 255,
36
+ 255,
37
+ 255,
38
+ 0.05
39
+ ); /* Original dark mode value */
40
+ --segmentedcontrol-selected-hover-bg: rgba(255, 255, 255, 0.05);
41
+ --segmentedcontrol-border: none;
42
+ --segmentedcontrol-border-radius: 0.353rem;
43
+ --segmentedcontrol-selected-border-radius: 0.353rem;
44
+ --segmentedcontrol-selected-border: none;
45
+ --segmentedcontrol-shadow-dark: rgba(
46
+ 0,
47
+ 0,
48
+ 0,
49
+ 0.21
50
+ ); /* Original dark mode value */
51
+ --segmentedcontrol-shadow-light: rgba(
52
+ 255,
53
+ 255,
54
+ 255,
55
+ 0.1
56
+ ); /* Original dark mode value */
57
+ --segmentedcontrol-box-shadow: 0px 1px 0px 0px
58
+ var(--segmentedcontrol-shadow-dark),
59
+ inset 0px 1px 0px 0px var(--segmentedcontrol-shadow-light);
60
+ }
@@ -0,0 +1,5 @@
1
+ export interface ControlItem {
2
+ title: string;
3
+ subtitle?: string;
4
+ disabled?: boolean;
5
+ }