@umbra.ui/core 0.2.0 → 0.4.0

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 (61) hide show
  1. package/dist/components/controls/InlineDropdown/InlineDropdown.vue +290 -0
  2. package/dist/components/controls/InlineDropdown/README.md +35 -0
  3. package/dist/components/controls/InlineDropdown/theme.css +40 -0
  4. package/dist/components/dialogs/Alert/Alert.vue +122 -11
  5. package/dist/components/dialogs/Alert/theme.css +20 -0
  6. package/dist/components/dialogs/Toast/useToast.d.ts +1 -1
  7. package/dist/components/inputs/AutogrowRichTextView/AutogrowRichTextView.vue +128 -0
  8. package/dist/components/inputs/AutogrowRichTextView/README.md +86 -0
  9. package/dist/components/inputs/AutogrowRichTextView/editor.css +211 -0
  10. package/dist/components/inputs/AutogrowRichTextView/theme.css +28 -0
  11. package/dist/components/inputs/InputCryptoAddress/InputCryptoAddress.vue +512 -0
  12. package/dist/components/inputs/InputCryptoAddress/README.md +45 -0
  13. package/dist/components/inputs/InputCryptoAddress/theme.css +80 -0
  14. package/dist/components/inputs/Tags/TagBar.vue +7 -4
  15. package/dist/components/inputs/Tags/theme.css +4 -0
  16. package/dist/components/inputs/search/README.md +64 -736
  17. package/dist/components/inputs/search/SearchOverlay.vue +376 -0
  18. package/dist/components/inputs/search/SearchResultCell.vue +205 -0
  19. package/dist/components/inputs/search/theme.css +66 -21
  20. package/dist/components/inputs/search/types.d.ts +27 -5
  21. package/dist/components/inputs/search/types.d.ts.map +1 -1
  22. package/dist/components/inputs/search/types.ts +33 -5
  23. package/dist/components/menus/ActionMenu/ActionMenu.vue +29 -7
  24. package/dist/components/menus/ActionMenu/theme.css +1 -1
  25. package/dist/components/menus/ActionMenu/types.d.ts +9 -0
  26. package/dist/components/menus/ActionMenu/types.d.ts.map +1 -0
  27. package/dist/components/menus/ActionMenu/types.js +1 -0
  28. package/dist/components/menus/ActionMenu/types.ts +9 -0
  29. package/dist/components/models/Popover/Popover.vue +6 -84
  30. package/dist/css/umbra-ui.css +1 -0
  31. package/dist/index.d.ts +7 -3
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +5 -2
  34. package/package.json +21 -16
  35. package/src/components/controls/InlineDropdown/InlineDropdown.vue +290 -0
  36. package/src/components/controls/InlineDropdown/README.md +35 -0
  37. package/src/components/controls/InlineDropdown/theme.css +40 -0
  38. package/src/components/dialogs/Alert/Alert.vue +122 -11
  39. package/src/components/dialogs/Alert/theme.css +20 -0
  40. package/src/components/inputs/AutogrowRichTextView/AutogrowRichTextView.vue +128 -0
  41. package/src/components/inputs/AutogrowRichTextView/README.md +86 -0
  42. package/src/components/inputs/AutogrowRichTextView/editor.css +211 -0
  43. package/src/components/inputs/AutogrowRichTextView/theme.css +28 -0
  44. package/src/components/inputs/InputCryptoAddress/InputCryptoAddress.vue +512 -0
  45. package/src/components/inputs/InputCryptoAddress/README.md +45 -0
  46. package/src/components/inputs/InputCryptoAddress/theme.css +80 -0
  47. package/src/components/inputs/Tags/TagBar.vue +7 -4
  48. package/src/components/inputs/Tags/theme.css +4 -0
  49. package/src/components/inputs/search/README.md +64 -736
  50. package/src/components/inputs/search/SearchOverlay.vue +376 -0
  51. package/src/components/inputs/search/SearchResultCell.vue +205 -0
  52. package/src/components/inputs/search/theme.css +66 -21
  53. package/src/components/inputs/search/types.ts +33 -5
  54. package/src/components/menus/ActionMenu/ActionMenu.vue +29 -7
  55. package/src/components/menus/ActionMenu/theme.css +1 -1
  56. package/src/components/menus/ActionMenu/types.ts +9 -0
  57. package/src/components/models/Popover/Popover.vue +6 -84
  58. package/src/index.ts +13 -3
  59. package/src/vue.d.ts +7 -26
  60. package/src/components/inputs/search/SearchBar.vue +0 -394
  61. package/src/components/inputs/search/SearchResults.vue +0 -310
@@ -1,8 +1,36 @@
1
- export interface SearchResult {
1
+ export interface SearchPathSegment {
2
2
  id: string;
3
- icon?: string;
3
+ type: string;
4
+ title: string;
5
+ }
6
+
7
+ export interface SearchOverlayResult {
8
+ id: string;
9
+ path: string;
10
+ pathSegments: SearchPathSegment[];
4
11
  title: string;
5
- description: string;
6
- caption: string;
7
- footnote: string;
12
+ excerpt: string;
13
+ }
14
+
15
+ export interface SearchResult extends SearchOverlayResult {
16
+ icon?: string;
17
+ description?: string;
18
+ caption?: string;
19
+ footnote?: string;
20
+ }
21
+
22
+ export interface SearchQueryOptions {
23
+ limit: number;
24
+ offset: number;
25
+ }
26
+
27
+ export interface SearchProvider<
28
+ T extends SearchOverlayResult = SearchOverlayResult
29
+ > {
30
+ search: (
31
+ query: string,
32
+ options: SearchQueryOptions
33
+ ) => Promise<{ results: T[]; total: number }>;
34
+ getRecent: () => Promise<T[]>;
35
+ select: (item: T) => Promise<void> | void;
8
36
  }
@@ -9,20 +9,15 @@ import {
9
9
  autoUpdate,
10
10
  } from "@floating-ui/vue";
11
11
  import { icons, type IconKey } from "@umbra.ui/icons";
12
+ import type { ActionMenuItem } from "./types";
12
13
  import "./theme.css";
13
14
 
14
- export interface ActionMenuItem {
15
- icon?: IconKey;
16
- title: string;
17
- action: () => void;
18
- isDestructive?: boolean;
19
- }
20
-
21
15
  // Props
22
16
  export interface Props {
23
17
  items: ActionMenuItem[];
24
18
  modelValue?: boolean;
25
19
  contextMenu?: boolean;
20
+ title?: string;
26
21
  }
27
22
 
28
23
  const props = withDefaults(defineProps<Props>(), {
@@ -237,6 +232,9 @@ defineExpose({
237
232
  @click="handleOverlayClick"
238
233
  ></div>
239
234
  <div v-if="showPopover" :class="$style.popup" ref="popup">
235
+ <div v-if="title" :class="$style.header">
236
+ <p :class="[$style.header_text, 'subheadline']">{{ title }}</p>
237
+ </div>
240
238
  <div
241
239
  v-for="item in items"
242
240
  :key="`action-item-${item.title}`"
@@ -259,6 +257,9 @@ defineExpose({
259
257
  >
260
258
  {{ item.title }}
261
259
  </p>
260
+ <span v-if="item.shortcutLabel" :class="$style.shortcut">
261
+ {{ item.shortcutLabel }}
262
+ </span>
262
263
  </div>
263
264
  </div>
264
265
  </Teleport>
@@ -303,6 +304,18 @@ defineExpose({
303
304
  border: var(--actionmenu-popup-border);
304
305
  }
305
306
 
307
+ .header {
308
+ padding: 0.471rem 0.588rem;
309
+ border-bottom: 1px solid var(--actionmenu-item-border);
310
+ background-color: var(--actionmenu-popup-bg);
311
+ }
312
+
313
+ .header_text {
314
+ margin: 0;
315
+ color: var(--actionmenu-item-text);
316
+ opacity: 0.7;
317
+ }
318
+
306
319
  @keyframes popupFadeIn {
307
320
  from {
308
321
  opacity: 0;
@@ -338,6 +351,15 @@ defineExpose({
338
351
  border-bottom: 0;
339
352
  }
340
353
 
354
+ .shortcut {
355
+ margin-left: auto;
356
+ font-size: 0.75rem;
357
+ letter-spacing: 0.04em;
358
+ opacity: 0.6;
359
+ color: var(--actionmenu-item-text);
360
+ font-variant-numeric: tabular-nums;
361
+ }
362
+
341
363
  .item_icon {
342
364
  width: 1.25rem;
343
365
  height: 1.25rem;
@@ -79,7 +79,7 @@
79
79
  --actionmenu-item-icon: #eeeeee; /* Original dark mode value */
80
80
 
81
81
  /* ActionMenu destructive colors */
82
- --actionmenu-destructive-text: #e5484d; /* Original dark mode value */
82
+ --actionmenu-destructive-text: #ec5d5e; /* Original dark mode value */
83
83
  --actionmenu-destructive-icon: #e5484d; /* Original dark mode value */
84
84
 
85
85
  /* ActionMenu overlay colors */
@@ -0,0 +1,9 @@
1
+ import type { IconKey } from "@umbra.ui/icons";
2
+
3
+ export interface ActionMenuItem {
4
+ icon?: IconKey;
5
+ title: string;
6
+ action: () => void;
7
+ shortcutLabel?: string;
8
+ isDestructive?: boolean;
9
+ }
@@ -20,7 +20,6 @@ import {
20
20
  type Middleware,
21
21
  } from "@floating-ui/vue";
22
22
  import gsap from "gsap";
23
- import "./theme.css";
24
23
 
25
24
  export interface PopoverProps {
26
25
  /**
@@ -106,6 +105,10 @@ export interface PopoverProps {
106
105
  * Background color of the popover
107
106
  */
108
107
  popoverBackground?: string;
108
+ /**
109
+ * Popover corner radius
110
+ */
111
+ popoverCornerRadius?: string;
109
112
  }
110
113
 
111
114
  const props = withDefaults(defineProps<PopoverProps>(), {
@@ -125,6 +128,7 @@ const props = withDefaults(defineProps<PopoverProps>(), {
125
128
  hoverShowDelay: 0,
126
129
  hoverHideDelay: 0,
127
130
  popoverBackground: "var(--popover-bg)",
131
+ popoverCornerRadius: "0.353rem",
128
132
  });
129
133
 
130
134
  const emit = defineEmits<{
@@ -153,6 +157,7 @@ const popoverStyles = computed(() => ({
153
157
  maxHeight: props.maxHeight,
154
158
  zIndex: props.zIndex + 1,
155
159
  backgroundColor: props.popoverBackground,
160
+ borderRadius: props.popoverCornerRadius,
156
161
  }));
157
162
 
158
163
  const overlayStyles = computed(() => ({
@@ -214,81 +219,6 @@ const updatePosition = async () => {
214
219
  }
215
220
  };
216
221
 
217
- const enableSmoothResize = () => {
218
- if (!popoverRef.value) return;
219
-
220
- let lastHeight = popoverRef.value.offsetHeight;
221
- let isFirstRun = true;
222
-
223
- const resizeObserver = new ResizeObserver((entries) => {
224
- // Skip the initial observation
225
- if (isFirstRun) {
226
- isFirstRun = false;
227
- return;
228
- }
229
-
230
- for (const entry of entries) {
231
- if (!popoverRef.value) continue;
232
-
233
- // Get the content wrapper's height
234
- const contentWrapper = popoverRef.value.lastElementChild as HTMLElement;
235
- if (!contentWrapper) continue;
236
-
237
- const newContentHeight = contentWrapper.offsetHeight;
238
-
239
- // Calculate total height including padding/borders
240
- const computedStyle = window.getComputedStyle(popoverRef.value);
241
- const paddingTop = parseFloat(computedStyle.paddingTop) || 0;
242
- const paddingBottom = parseFloat(computedStyle.paddingBottom) || 0;
243
- const borderTop = parseFloat(computedStyle.borderTopWidth) || 0;
244
- const borderBottom = parseFloat(computedStyle.borderBottomWidth) || 0;
245
-
246
- const newHeight =
247
- newContentHeight +
248
- paddingTop +
249
- paddingBottom +
250
- borderTop +
251
- borderBottom;
252
-
253
- // Only animate if height actually changed significantly
254
- if (Math.abs(lastHeight - newHeight) > 1) {
255
- // Kill any existing animations on this element
256
- gsap.killTweensOf(popoverRef.value);
257
-
258
- // Animate height change
259
- gsap.fromTo(
260
- popoverRef.value,
261
- {
262
- height: lastHeight,
263
- },
264
- {
265
- height: newHeight,
266
- duration: 0.3,
267
- ease: "power2.inOut",
268
- onComplete: () => {
269
- lastHeight = newHeight;
270
- updatePosition();
271
- },
272
- }
273
- );
274
-
275
- break; // Only process one change at a time
276
- }
277
- }
278
- });
279
-
280
- // Find the popoverContent div
281
- const contentWrapper = popoverRef.value.lastElementChild as HTMLElement;
282
- if (contentWrapper) {
283
- // Only observe direct children, not the wrapper itself
284
- Array.from(contentWrapper.children).forEach((child) => {
285
- resizeObserver.observe(child as HTMLElement);
286
- });
287
- }
288
-
289
- return resizeObserver;
290
- };
291
-
292
222
  // Animation functions
293
223
  const open = async () => {
294
224
  if (isAnimating.value || isVisible.value) return;
@@ -381,13 +311,6 @@ const open = async () => {
381
311
  onComplete: () => {
382
312
  isAnimating.value = false;
383
313
  emit("after-enter");
384
-
385
- // Set up smooth resizing AFTER animation completes
386
- if (popoverRef.value) {
387
- const resizeObserver = enableSmoothResize();
388
- // Store it for cleanup
389
- (popoverRef.value as any)._resizeObserver = resizeObserver;
390
- }
391
314
  },
392
315
  });
393
316
 
@@ -652,7 +575,6 @@ defineExpose({
652
575
  position: absolute;
653
576
  top: 0;
654
577
  left: 0;
655
- border-radius: 0.353rem;
656
578
  box-shadow: 0px 1px 0px 0px var(--popover-shadow),
657
579
  inset 0px 1px 0px 0px var(--popover-inset-shadow);
658
580
  border: var(--popover-border);
package/src/index.ts CHANGED
@@ -34,11 +34,13 @@ export { default as SegmentedControl } from "./components/controls/SegmentedCont
34
34
  export { type ControlItem } from "./components/controls/SegmentedControl/types";
35
35
  export { default as Dropdown } from "./components/controls/Dropdown/Dropdown.vue";
36
36
  export { type DropdownItem } from "./components/controls/Dropdown/types";
37
+ export { default as InlineDropdown } from "./components/controls/InlineDropdown/InlineDropdown.vue";
37
38
  export { default as Radio } from "./components/controls/Radio/Radio.vue";
38
39
  export { default as Slider } from "./components/controls/Slider/Slider.vue";
39
40
  export { default as RangeSlider } from "./components/controls/RangeSlider/RangeSlider.vue";
40
41
  export { default as Stepper } from "./components/controls/Stepper/Stepper.vue";
41
42
  export { default as InputText } from "./components/inputs/InputText/InputText.vue";
43
+ export { default as InputCryptoAddress } from "./components/inputs/InputCryptoAddress/InputCryptoAddress.vue";
42
44
  export { default as InputSecure } from "./components/inputs/InputSecure/InputSecure.vue";
43
45
  export { default as InputPhone } from "./components/inputs/InputPhone/InputPhone.vue";
44
46
  export { default as InputNumber } from "./components/inputs/InputNumber/InputNumber.vue";
@@ -77,8 +79,10 @@ export {
77
79
  } from "./components/inputs/Tags/types";
78
80
  export { type TagBarStyle } from "./components/inputs/Tags/tag-bar-styles";
79
81
  export { default as AutogrowTextView } from "./components/inputs/AutogrowTextView/AutogrowTextView.vue";
82
+ export { default as AutogrowRichTextView } from "./components/inputs/AutogrowRichTextView/AutogrowRichTextView.vue";
80
83
  export { default as StringCapture } from "./components/inputs/StringCapture/StringCapture.vue";
81
84
  export { default as ActionMenu } from "./components/menus/ActionMenu/ActionMenu.vue";
85
+ export { type ActionMenuItem } from "./components/menus/ActionMenu/types";
82
86
  export { default as Tooltip } from "./components/indicators/Tooltip/TooltipProvider.vue";
83
87
  export { useTooltip } from "./components/indicators/Tooltip/useTooltip";
84
88
  export { vTooltip } from "./components/indicators/Tooltip/tooltip";
@@ -96,9 +100,15 @@ export {
96
100
  type ToastInstance,
97
101
  } from "./components/dialogs/Toast/types";
98
102
  export { default as OTP } from "./components/inputs/OTP/OTP.vue";
99
- export { default as SearchBar } from "./components/inputs/search/SearchBar.vue";
100
- export { default as SearchResults } from "./components/inputs/search/SearchResults.vue";
101
- export { type SearchResult } from "./components/inputs/search/types";
103
+ export { default as SearchOverlay } from "./components/inputs/search/SearchOverlay.vue";
104
+ export { default as SearchResultCell } from "./components/inputs/search/SearchResultCell.vue";
105
+ export {
106
+ type SearchOverlayResult,
107
+ type SearchPathSegment,
108
+ type SearchProvider,
109
+ type SearchQueryOptions,
110
+ type SearchResult,
111
+ } from "./components/inputs/search/types";
102
112
  export { default as Sheet } from "./components/models/Sheet/Sheet.vue";
103
113
  export { default as Sidebar } from "./components/models/Sidebar/Sidebar.vue";
104
114
  export { default as Popover } from "./components/models/Popover/Popover.vue";
package/src/vue.d.ts CHANGED
@@ -4,32 +4,6 @@ declare module "*.vue" {
4
4
  export default component;
5
5
  }
6
6
 
7
- declare module "./components/inputs/search/SearchResults.vue" {
8
- import type { DefineComponent } from "vue";
9
- import type { BaseSearchResult } from "./components/inputs/search/types";
10
-
11
- interface SearchResultsSlots<T extends BaseSearchResult> {
12
- result: (props: {
13
- item: T;
14
- index: number;
15
- highlight: (text: string) => string;
16
- }) => any;
17
- empty: () => any;
18
- }
19
-
20
- const component: DefineComponent<
21
- {},
22
- {},
23
- any,
24
- {},
25
- {},
26
- {},
27
- {},
28
- SearchResultsSlots<any>
29
- >;
30
- export default component;
31
- }
32
-
33
7
  declare module "autosize" {
34
8
  function autosize(element: HTMLTextAreaElement): void;
35
9
  namespace autosize {
@@ -43,3 +17,10 @@ declare module "*.md?raw" {
43
17
  const content: string;
44
18
  export default content;
45
19
  }
20
+
21
+ declare module "@umbra.ui/core" {
22
+ import type { DefineComponent } from "vue";
23
+
24
+ export const InlineDropdown: DefineComponent<{}, {}, any>;
25
+ export const InputCryptoAddress: DefineComponent<{}, {}, any>;
26
+ }