oneslash-design-system 1.4.0 → 1.6.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 (35) hide show
  1. package/dist/components/alert.jsx +1 -1
  2. package/dist/components/button.d.ts +1 -1
  3. package/dist/components/button.jsx +6 -4
  4. package/dist/components/icon.d.ts +1 -1
  5. package/dist/components/icon.jsx +1 -0
  6. package/dist/components/iconButton.d.ts +1 -1
  7. package/dist/components/iconButton.jsx +9 -10
  8. package/dist/components/loadingScreen.d.ts +1 -1
  9. package/dist/components/loadingScreen.jsx +1 -0
  10. package/dist/components/menuItem.d.ts +1 -1
  11. package/dist/components/menuItem.jsx +7 -5
  12. package/dist/components/tab.d.ts +2 -1
  13. package/dist/components/tab.jsx +22 -11
  14. package/dist/components/tabsContainer.d.ts +1 -0
  15. package/dist/components/tabsContainer.jsx +68 -4
  16. package/dist/components/tag.d.ts +1 -1
  17. package/dist/components/tag.jsx +6 -2
  18. package/dist/components/textField.d.ts +1 -1
  19. package/dist/components/textField.jsx +1 -0
  20. package/dist/components/textarea.d.ts +1 -1
  21. package/dist/components/textarea.jsx +1 -0
  22. package/dist/components/tooltip.jsx +25 -11
  23. package/dist/designTokens.js +5 -5
  24. package/dist/output.css +144 -31
  25. package/dist/stories/Button.stories.jsx +2 -1
  26. package/dist/stories/Icon.stories.jsx +1 -1
  27. package/dist/stories/IconButton.stories.jsx +2 -1
  28. package/dist/stories/MenuItem.stories.jsx +1 -1
  29. package/dist/stories/TabsContainer.stories.d.ts +2 -0
  30. package/dist/stories/TabsContainer.stories.jsx +14 -2
  31. package/dist/stories/Tag.stories.jsx +1 -1
  32. package/dist/stories/TextField.stories.jsx +1 -1
  33. package/dist/stories/Textarea.stories.jsx +1 -1
  34. package/dist/tsconfig.tsbuildinfo +1 -1
  35. package/package.json +6 -2
@@ -50,7 +50,7 @@ export default function Alert(_a) {
50
50
  if (!shouldRender)
51
51
  return null;
52
52
  var bgClasses = (_b = bgClassMap[type]) !== null && _b !== void 0 ? _b : bgClassMap.default;
53
- var alertContent = (<div className={"flex items-start justify-between w-full p-2 rounded-[8px] transition-opacity duration-200 ease-out ".concat(bgClasses, " ").concat(isVisible ? 'opacity-100' : 'opacity-0', " ").concat(variant === 'toast' ? 'max-w-md pointer-events-auto' : '')}>
53
+ var alertContent = (<div className={"flex items-start justify-between w-full p-2 rounded-[8px] transition-[opacity,transform] duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] motion-reduce:transition-none ".concat(bgClasses, " ").concat(isVisible ? 'opacity-100 translate-y-0 scale-100' : variant === 'toast' ? 'opacity-0 -translate-y-3 scale-95' : 'opacity-0', " ").concat(variant === 'toast' ? 'max-w-md pointer-events-auto' : '')}>
54
54
  <div className="flex items-start gap-2 text-light-text-primary dark:text-dark-text-primary">
55
55
  <div className="flex flex-col text-left">
56
56
  <span className="text-body2">{message}</span>
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  interface ButtonProps {
3
- size: 'small' | 'medium' | 'large';
3
+ size: 'tiny' | 'small' | 'medium' | 'large';
4
4
  type: 'primary' | 'secondary' | 'tertiary' | 'textOnly';
5
5
  color?: 'default' | 'danger';
6
6
  state: 'enabled' | 'hovered' | 'focused' | 'disabled' | 'selected';
@@ -94,11 +94,13 @@ export default function Button(_a) {
94
94
  large: 'text-body1 p-2',
95
95
  medium: 'text-body1 p-1',
96
96
  small: 'text-body2 p-1',
97
+ tiny: 'text-caption px-1 py-px',
97
98
  }[size];
98
99
  var sizeIcon = {
99
100
  large: 'w-6 h-6',
100
101
  medium: 'w-5 h-5',
101
102
  small: 'w-4 h-4',
103
+ tiny: 'w-3.5 h-3.5',
102
104
  }[size];
103
105
  var baseTypeClasses = {
104
106
  default: {
@@ -109,7 +111,7 @@ export default function Button(_a) {
109
111
  },
110
112
  danger: {
111
113
  primary: 'bg-light-error-main dark:bg-dark-error-main text-light-error-contrast dark:text-dark-error-contrast',
112
- secondary: 'bg-light-error-light dark:bg-dark-error-light text-light-error-main dark:text-dark-error-main',
114
+ secondary: 'bg-light-error-alertBg dark:bg-dark-error-alertBg text-light-error-dark dark:text-dark-error-light',
113
115
  tertiary: 'bg-transparent border border-light-error-main dark:border-dark-error-main text-light-error-main dark:text-dark-error-main',
114
116
  textOnly: 'text-light-error-main dark:text-dark-error-main',
115
117
  },
@@ -123,7 +125,7 @@ export default function Button(_a) {
123
125
  },
124
126
  danger: {
125
127
  primary: 'hover:bg-light-error-dark hover:dark:bg-dark-error-dark',
126
- secondary: 'hover:bg-light-error-main/20 dark:hover:bg-dark-error-main/20',
128
+ secondary: 'hover:bg-light-error-light/60 dark:hover:bg-dark-error-dark/60',
127
129
  tertiary: 'hover:bg-light-error-main/10 dark:hover:bg-dark-error-main/10',
128
130
  textOnly: 'hover:bg-light-error-main/10 dark:hover:bg-dark-error-main/10',
129
131
  },
@@ -146,9 +148,9 @@ export default function Button(_a) {
146
148
  {/* Group IconLeft and label in a flex container for left alignment */}
147
149
  <div className="flex items-center">
148
150
  {IconLeft && <IconLeft className={sizeIcon} strokeWidth={2}/>}
149
- <div className="flex flex-col text-center px-2">
151
+ <div className={"flex flex-col text-center ".concat(size === 'tiny' ? 'px-1' : 'px-2')}>
150
152
  <span className="whitespace-nowrap overflow-hidden truncate">{label}</span>
151
- {secondLabel && (<span className="whitespace-nowrap overflow-hidden truncate text-body2 opacity-70">{secondLabel}</span>)}
153
+ {secondLabel && (<span className={"whitespace-nowrap overflow-hidden truncate ".concat(size === 'tiny' ? 'text-caption' : 'text-body2', " opacity-70")}>{secondLabel}</span>)}
152
154
  </div>
153
155
  </div>
154
156
  {IconRight && (<div onClick={onClickActionIcon} className="cursor-pointer">
@@ -3,7 +3,7 @@ import { icons } from 'lucide-react';
3
3
  type IconName = keyof typeof icons;
4
4
  interface IconProps {
5
5
  name: IconName;
6
- size?: 'small' | 'medium' | 'large' | number;
6
+ size?: 'tiny' | 'small' | 'medium' | 'large' | number;
7
7
  color?: 'primary' | 'secondary' | 'disabled' | 'error' | 'warning' | 'success' | 'info' | 'accent' | 'inherit';
8
8
  strokeWidth?: number;
9
9
  className?: string;
@@ -2,6 +2,7 @@
2
2
  import React from 'react';
3
3
  import { icons } from 'lucide-react';
4
4
  var sizeMap = {
5
+ tiny: 12,
5
6
  small: 16,
6
7
  medium: 24,
7
8
  large: 32,
@@ -3,7 +3,7 @@ import * as LucideIcons from 'lucide-react';
3
3
  interface IconButtonProps {
4
4
  color: "primary" | "secondary" | "tertiary" | "iconOnly";
5
5
  state: "enabled" | "selected" | "disabled";
6
- size: "large" | "medium" | "small";
6
+ size: "large" | "medium" | "small" | "tiny";
7
7
  iconName: keyof typeof LucideIcons;
8
8
  onClick?: any;
9
9
  loading?: boolean;
@@ -4,8 +4,7 @@ import * as LucideIcons from 'lucide-react';
4
4
  import { LoadingSmall } from './loadingScreen';
5
5
  export default function IconButton(_a) {
6
6
  var color = _a.color, state = _a.state, size = _a.size, iconName = _a.iconName, onClick = _a.onClick, _b = _a.loading, loading = _b === void 0 ? false : _b;
7
- var _c = useState(false), isHovered = _c[0], setIsHovered = _c[1];
8
- var _d = useState(null), Icon = _d[0], setIcon = _d[1];
7
+ var _c = useState(null), Icon = _c[0], setIcon = _c[1];
9
8
  // Load icon from Lucide
10
9
  useEffect(function () {
11
10
  if (iconName) {
@@ -17,11 +16,13 @@ export default function IconButton(_a) {
17
16
  large: 'p-2', // 8px padding
18
17
  medium: 'p-1', // 4px padding
19
18
  small: 'p-1', // 4px padding
19
+ tiny: 'p-0.5', // 2px padding
20
20
  };
21
21
  var iconSizeClasses = {
22
22
  large: 'size-6', // 24px
23
23
  medium: 'size-6', // 24px
24
24
  small: 'size-5', // 20px
25
+ tiny: 'size-4', // 16px
25
26
  };
26
27
  // Base classes (padding and corner radius)
27
28
  var baseClasses = "".concat(sizeClasses[size], " rounded-[8px] leading-none relative");
@@ -39,12 +40,12 @@ export default function IconButton(_a) {
39
40
  var bgColorHover = state === 'selected'
40
41
  ? '' // No hover effect when selected
41
42
  : color === 'primary'
42
- ? 'hover:bg-light-accent-dark hover:dark:bg-dark-accent-dark' // Primary
43
+ ? 'hover:bg-light-accent-dark/75 hover:dark:bg-dark-accent-dark/75' // Primary
43
44
  : color === 'secondary'
44
- ? 'hover:bg-light-secondary-dark hover:dark:bg-dark-secondary-dark' // Secondary
45
+ ? 'hover:bg-light-secondary-dark/75 hover:dark:bg-dark-secondary-dark/75' // Secondary
45
46
  : color === 'tertiary'
46
- ? 'hover:bg-light-background-accent200 hover:dark:bg-dark-background-accent200' // Tertiary
47
- : 'hover:bg-light-background-accent200 hover:dark:bg-dark-background-accent200'; // iconOnly
47
+ ? 'hover:bg-light-background-accent200/75 hover:dark:bg-dark-background-accent200/75' // Tertiary
48
+ : 'hover:bg-light-background-accent200/75 hover:dark:bg-dark-background-accent200/75'; // iconOnly
48
49
  // Icon color
49
50
  var iconColor = state === 'selected'
50
51
  ? 'text-light-text-contrast dark:text-dark-text-contrast' // Selected state
@@ -62,11 +63,9 @@ export default function IconButton(_a) {
62
63
  ? 'cursor-not-allowed opacity-50'
63
64
  : state === 'selected'
64
65
  ? 'cursor-pointer'
65
- : isHovered
66
- ? 'cursor-pointer hover:bg-opacity-75'
67
- : 'cursor-pointer';
66
+ : 'cursor-pointer';
68
67
  return (<button className={"".concat(baseClasses, " ").concat(bgColor, " ").concat(iconColor, " ").concat(bgColorHover, " ").concat(stateClasses, " transition-colors duration-200 ease-in-out flex items-center justify-center")} disabled={state === 'disabled' || loading} // Disable button during loading
69
- onMouseEnter={function () { return setIsHovered(true); }} onMouseLeave={function () { return setIsHovered(false); }} onClick={onClick} aria-label={loading ? 'Loading' : 'Reload'}>
68
+ onClick={onClick} aria-label={loading ? 'Loading' : 'Reload'}>
70
69
  {loading ? (<LoadingSmall size={size}/>) : (Icon && <Icon className={iconSizeClasses[size]} strokeWidth={2}/>)}
71
70
  </button>);
72
71
  }
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  interface LoadingSmallProps {
3
- size?: 'large' | 'medium' | 'small';
3
+ size?: 'large' | 'medium' | 'small' | 'tiny';
4
4
  }
5
5
  export default function LoadingScreen(): React.JSX.Element;
6
6
  export declare function LoadingSmall({ size }: LoadingSmallProps): React.JSX.Element;
@@ -12,6 +12,7 @@ export function LoadingSmall(_a) {
12
12
  large: 'w-6 h-6 border-2', // 24px, border-2 for proportional thickness
13
13
  medium: 'w-6 h-6 border-2', // 24px, border-2
14
14
  small: 'w-5 h-5 border-2', // 20px, slightly thinner border
15
+ tiny: 'w-4 h-4 border-2', // 16px
15
16
  };
16
17
  return (<div className="flex justify-center items-center">
17
18
  <div className={"rounded-full border-t-transparent border-r-light-text-primary border-b-light-text-primary border-l-light-text-primary dark:border-t-transparent dark:border-r-dark-text-primary dark:border-b-dark-text-primary dark:border-l-dark-text-primary animate-spin ".concat(spinnerSizeClasses[size])}/>
@@ -10,7 +10,7 @@ interface MenuItemProps {
10
10
  isSelected?: boolean;
11
11
  onClick?: any;
12
12
  className?: string;
13
- size?: 'small' | 'medium';
13
+ size?: 'tiny' | 'small' | 'medium';
14
14
  tag?: {
15
15
  label: React.ReactNode;
16
16
  iconName?: string;
@@ -93,10 +93,12 @@ export default function MenuItem(_a) {
93
93
  fetchIcon();
94
94
  }, [iconName, iconRight, loadIcon]);
95
95
  // Size-based icon and text classes
96
- var iconSize = size === 'small' ? 'w-5 h-5' : 'w-6 h-6';
97
- var labelClass = size === 'small' ? 'text-body2' : 'text-body1';
98
- var tagSize = size === 'small' ? 'small' : 'medium';
99
- var content = (<div className={"\n flex items-center p-2 rounded-[8px] cursor-pointer justify-between transition-colors duration-200 ease-in-out\n ".concat(isSelected
96
+ var iconSize = { tiny: 'w-4 h-4', small: 'w-5 h-5', medium: 'w-6 h-6' }[size];
97
+ var labelClass = { tiny: 'text-caption', small: 'text-body2', medium: 'text-body1' }[size];
98
+ var secondLabelClass = size === 'tiny' ? 'text-caption' : 'text-body2';
99
+ var tagSize = { tiny: 'tiny', small: 'small', medium: 'medium' }[size];
100
+ var paddingClass = size === 'tiny' ? 'p-1' : 'p-2';
101
+ var content = (<div className={"\n flex items-center ".concat(paddingClass, " rounded-[8px] cursor-pointer justify-between transition-colors duration-200 ease-in-out\n ").concat(isSelected
100
102
  ? 'bg-light-primary-dark dark:bg-dark-primary-dark text-light-text-contrast dark:text-dark-text-contrast'
101
103
  : 'hover:bg-light-background-accent200 hover:dark:bg-dark-background-accent200', "\n ").concat(className, "\n ")} style={{ width: '100%' }} onClick={onClick}>
102
104
  {/* Left group: icon/userImg + label with 8px gap */}
@@ -106,7 +108,7 @@ export default function MenuItem(_a) {
106
108
  <span className={"truncate ".concat(labelClass, " ").concat(isSelected ? 'text-light-text-contrast dark:text-dark-text-contrast' : 'text-light-text-primary dark:text-dark-text-primary')}>
107
109
  {label}
108
110
  </span>
109
- {secondLabel && (<span className={"truncate text-body2 opacity-70 ".concat(isSelected ? 'text-light-text-contrast dark:text-dark-text-contrast' : 'text-light-text-primary dark:text-dark-text-primary')}>
111
+ {secondLabel && (<span className={"truncate ".concat(secondLabelClass, " opacity-70 ").concat(isSelected ? 'text-light-text-contrast dark:text-dark-text-contrast' : 'text-light-text-primary dark:text-dark-text-primary')}>
110
112
  {secondLabel}
111
113
  </span>)}
112
114
  </div>
@@ -12,6 +12,7 @@ type TabProps = {
12
12
  decoIcon?: string;
13
13
  actionIcon?: string;
14
14
  router?: RouterLike;
15
+ size?: 'medium' | 'small' | 'tiny';
15
16
  };
16
- export default function Tab({ label, secondLabel, href, isSelected, onClickTab, onClickActionIcon, decoIcon, actionIcon, router }: TabProps): React.JSX.Element;
17
+ export default function Tab({ label, secondLabel, href, isSelected, onClickTab, onClickActionIcon, decoIcon, actionIcon, router, size, }: TabProps): React.JSX.Element;
17
18
  export {};
@@ -35,12 +35,14 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
35
35
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
36
  }
37
37
  };
38
- import React, { useState, useEffect, useCallback } from 'react';
38
+ import React, { useState, useEffect, useCallback, useContext } from 'react';
39
+ import { TabsContainerContext } from './tabsContainer';
39
40
  export default function Tab(_a) {
40
41
  var _this = this;
41
- var label = _a.label, secondLabel = _a.secondLabel, href = _a.href, isSelected = _a.isSelected, onClickTab = _a.onClickTab, onClickActionIcon = _a.onClickActionIcon, decoIcon = _a.decoIcon, actionIcon = _a.actionIcon, router = _a.router;
42
- var _b = useState(null), IconLeft = _b[0], setIconLeft = _b[1];
43
- var _c = useState(null), IconRight = _c[0], setIconRight = _c[1];
42
+ var label = _a.label, secondLabel = _a.secondLabel, href = _a.href, isSelected = _a.isSelected, onClickTab = _a.onClickTab, onClickActionIcon = _a.onClickActionIcon, decoIcon = _a.decoIcon, actionIcon = _a.actionIcon, router = _a.router, _b = _a.size, size = _b === void 0 ? 'medium' : _b;
43
+ var inContainer = useContext(TabsContainerContext);
44
+ var _c = useState(null), IconLeft = _c[0], setIconLeft = _c[1];
45
+ var _d = useState(null), IconRight = _d[0], setIconRight = _d[1];
44
46
  // Load icon dynamically
45
47
  var loadIcon = useCallback(function (iconName) { return __awaiter(_this, void 0, void 0, function () {
46
48
  var module_1, Icon, error_1;
@@ -96,20 +98,29 @@ export default function Tab(_a) {
96
98
  router.push(href);
97
99
  }
98
100
  };
99
- return (<div className={"\n flex items-center space-x-1 py-1 px-[6px] rounded-[8px] cursor-pointer justify-start transition-colors duration-200 ease-in-out\n ".concat(isSelected
100
- ? 'bg-light-primary-dark dark:bg-dark-primary-dark text-light-text-contrast dark:text-dark-text-contrast'
101
+ var sizeClasses = {
102
+ medium: { tab: 'py-1 px-[6px]', label: 'px-[6px] text-body1', secondLabel: 'text-body2', icon: 'w-6 h-6' },
103
+ small: { tab: 'py-1 px-[6px]', label: 'px-1 text-body2', secondLabel: 'text-caption', icon: 'w-5 h-5' },
104
+ tiny: { tab: 'py-0.5 px-1', label: 'px-1 text-caption', secondLabel: 'text-caption', icon: 'w-4 h-4' },
105
+ }[size];
106
+ // Inside a TabsContainer the container's sliding pill is the selected background
107
+ var selectedClasses = inContainer
108
+ ? 'text-light-text-contrast dark:text-dark-text-contrast'
109
+ : 'bg-light-primary-dark dark:bg-dark-primary-dark text-light-text-contrast dark:text-dark-text-contrast';
110
+ return (<div data-tab-selected={isSelected} className={"\n relative flex items-center space-x-1 rounded-[8px] cursor-pointer justify-start transition-colors duration-200 ease-in-out\n ".concat(sizeClasses.tab, "\n ").concat(isSelected
111
+ ? selectedClasses
101
112
  : 'text-light-text-primary dark:text-dark-text-primary hover:bg-light-background-accent200 dark:hover:bg-dark-background-accent200', "\n ")} onClick={handleClick}>
102
- {IconLeft && <IconLeft className="w-6 h-6" strokeWidth={2}/>}
103
- <div className="flex flex-col px-[6px] text-center">
104
- <span className="whitespace-nowrap text-body1">
113
+ {IconLeft && <IconLeft className={sizeClasses.icon} strokeWidth={2}/>}
114
+ <div className={"flex flex-col text-center ".concat(sizeClasses.label)}>
115
+ <span className="whitespace-nowrap">
105
116
  {label}
106
117
  </span>
107
- {secondLabel && (<span className="whitespace-nowrap text-body2 opacity-70">
118
+ {secondLabel && (<span className={"whitespace-nowrap opacity-70 ".concat(sizeClasses.secondLabel)}>
108
119
  {secondLabel}
109
120
  </span>)}
110
121
  </div>
111
122
  {IconRight && (<div onClick={onClickActionIcon} className="cursor-pointer">
112
- <IconRight className="w-6 h-6" strokeWidth={2}/>
123
+ <IconRight className={sizeClasses.icon} strokeWidth={2}/>
113
124
  </div>)}
114
125
  </div>);
115
126
  }
@@ -2,5 +2,6 @@ import React from 'react';
2
2
  interface TabsContainerProps {
3
3
  children: React.ReactNode;
4
4
  }
5
+ export declare const TabsContainerContext: React.Context<boolean>;
5
6
  export default function TabsContainer({ children, }: TabsContainerProps): React.JSX.Element;
6
7
  export {};
@@ -1,12 +1,76 @@
1
1
  'use client';
2
- import React from 'react';
2
+ import React, { createContext, useLayoutEffect, useRef, useState } from 'react';
3
+ // Lets a Tab know a container draws its selected background (the sliding pill)
4
+ export var TabsContainerContext = createContext(false);
3
5
  export default function TabsContainer(_a) {
4
6
  var children = _a.children;
5
7
  var tabCount = React.Children.count(children);
6
- return (<div className={"\n flex space-x-2 p-1 rounded-[12px] overflow-x-auto\n ".concat(tabCount > 0 ? 'bg-light-background-accent100 dark:bg-dark-background-accent100' : 'bg-transparent', "\n ")} style={{
8
+ var containerRef = useRef(null);
9
+ var selectedRef = useRef(null);
10
+ var _b = useState(null), indicator = _b[0], setIndicator = _b[1];
11
+ useLayoutEffect(function () {
12
+ var _a;
13
+ var container = containerRef.current;
14
+ if (!container)
15
+ return;
16
+ var update = function () {
17
+ var selected = container.querySelector('[data-tab-selected="true"]');
18
+ if (!selected) {
19
+ selectedRef.current = null;
20
+ setIndicator(null);
21
+ return;
22
+ }
23
+ setIndicator(function (prev) { return ({
24
+ animate: prev !== null,
25
+ x: selected.offsetLeft,
26
+ y: selected.offsetTop,
27
+ width: selected.offsetWidth,
28
+ height: selected.offsetHeight,
29
+ }); });
30
+ // Tabs scroll horizontally instead of wrapping; keep a newly selected tab in view
31
+ if (selected !== selectedRef.current) {
32
+ selectedRef.current = selected;
33
+ var left = selected.offsetLeft;
34
+ var right = left + selected.offsetWidth;
35
+ if (left < container.scrollLeft) {
36
+ container.scrollTo({ left: left - 4, behavior: 'smooth' });
37
+ }
38
+ else if (right > container.scrollLeft + container.clientWidth) {
39
+ container.scrollTo({ left: right - container.clientWidth + 4, behavior: 'smooth' });
40
+ }
41
+ }
42
+ };
43
+ update();
44
+ // Tab widths change once web fonts load
45
+ (_a = document.fonts) === null || _a === void 0 ? void 0 : _a.ready.then(update);
46
+ var resizeObserver = new ResizeObserver(update);
47
+ resizeObserver.observe(container);
48
+ Array.from(container.children).forEach(function (child) { return resizeObserver.observe(child); });
49
+ var mutationObserver = new MutationObserver(update);
50
+ mutationObserver.observe(container, {
51
+ subtree: true,
52
+ childList: true,
53
+ attributes: true,
54
+ attributeFilter: ['data-tab-selected'],
55
+ });
56
+ return function () {
57
+ resizeObserver.disconnect();
58
+ mutationObserver.disconnect();
59
+ };
60
+ }, [children]);
61
+ return (<TabsContainerContext.Provider value={true}>
62
+ <div ref={containerRef} className={"\n relative flex gap-2 p-1 rounded-[12px] overflow-x-auto\n ".concat(tabCount > 0 ? 'bg-light-background-accent100 dark:bg-dark-background-accent100' : 'bg-transparent', "\n ")} style={{
7
63
  scrollbarWidth: 'none',
8
64
  msOverflowStyle: 'none',
9
65
  }}>
10
- {children}
11
- </div>);
66
+ {indicator && (<span aria-hidden className={"absolute rounded-[8px] pointer-events-none bg-light-primary-dark dark:bg-dark-primary-dark\n ".concat(indicator.animate ? 'transition-[transform,width,height] duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] motion-reduce:transition-none' : '')} style={{
67
+ top: 0,
68
+ left: 0,
69
+ transform: "translate(".concat(indicator.x, "px, ").concat(indicator.y, "px)"),
70
+ width: indicator.width,
71
+ height: indicator.height,
72
+ }}/>)}
73
+ {children}
74
+ </div>
75
+ </TabsContainerContext.Provider>);
12
76
  }
@@ -3,7 +3,7 @@ import { icons } from 'lucide-react';
3
3
  type IconName = keyof typeof icons;
4
4
  interface TagProps {
5
5
  variant: 'contained' | 'textOnly' | 'dot';
6
- size: 'medium' | 'small';
6
+ size: 'medium' | 'small' | 'tiny';
7
7
  state?: 'enabled' | 'selected';
8
8
  color?: 'default' | 'success' | 'warning' | 'error' | 'info';
9
9
  label: React.ReactNode;
@@ -49,7 +49,11 @@ export default function Tag(_a) {
49
49
  // Get icon directly from icons map
50
50
  var Icon = iconName ? icons[iconName] : null;
51
51
  // Size and padding
52
- var sizeClasses = size === 'medium' ? 'text-body2 px-2 py-1' : 'text-caption px-2 py-[3px]';
52
+ var sizeClasses = {
53
+ medium: 'text-body2 px-2 py-1',
54
+ small: 'text-caption px-2 py-[3px]',
55
+ tiny: 'text-caption px-1.5 py-0',
56
+ }[size];
53
57
  // Selected state styles
54
58
  var isSelected = state === 'selected';
55
59
  // When color is provided, use color-based styling
@@ -112,7 +116,7 @@ export default function Tag(_a) {
112
116
  var baseClasses = 'flex space-x-2 items-center gap-1 rounded-full whitespace-nowrap transition-colors duration-200 ease-in-out';
113
117
  return (<div className={"".concat(baseClasses, " ").concat(sizeClasses, " ").concat(bgClasses, " ").concat(fontClasses, " ").concat(borderClasses, " ").concat(hoverClasses, " ").concat(cursorClass)} onMouseEnter={function () { return onClick && setIsHovered(true); }} onMouseLeave={function () { return onClick && setIsHovered(false); }} onClick={onClick}>
114
118
  {variant === 'dot' && (<span className={"w-3 h-3 rounded-full flex-shrink-0 ".concat(dotColor)}/>)}
115
- {Icon && variant !== 'dot' && <Icon className="w-4 h-4 flex-shrink-0" strokeWidth={2}/>}
119
+ {Icon && variant !== 'dot' && <Icon className={"".concat(size === 'tiny' ? 'w-3 h-3' : 'w-4 h-4', " flex-shrink-0")} strokeWidth={2}/>}
116
120
  <div className="flex flex-col text-center">
117
121
  <span>{label}</span>
118
122
  {secondLabel && (<span className="text-caption opacity-70">{secondLabel}</span>)}
@@ -15,7 +15,7 @@ interface TextFieldProps {
15
15
  disabled?: boolean;
16
16
  error?: boolean;
17
17
  required?: boolean;
18
- size?: 'large' | 'medium' | 'small';
18
+ size?: 'large' | 'medium' | 'small' | 'tiny';
19
19
  placeholder?: string;
20
20
  }
21
21
  export default function TextField({ id, label, value, type, onChange, onBlur, onFocus, onKeyDown, onSubmit, autoFocus, multiline, maxRows, disabled, error, required, size, placeholder, }: TextFieldProps): React.JSX.Element;
@@ -17,6 +17,7 @@ export default function TextField(_a) {
17
17
  large: 'text-body1 p-2 leading-[22px]', // body1 (16px), padding 8px
18
18
  medium: 'text-body1 p-2 leading-[22px]', // body1 (16px), padding 8px
19
19
  small: 'text-body2 p-2 leading-[18px]', // body2 (14px), padding 8px
20
+ tiny: 'text-caption p-1 leading-[16px]', // caption (12px), padding 4px
20
21
  }[size];
21
22
  var baseClasses = 'w-full border rounded-[8px] outline-none';
22
23
  var textColor = 'text-light-text-primary dark:text-dark-text-primary';
@@ -14,7 +14,7 @@ interface TextareaProps {
14
14
  maxRows?: number;
15
15
  disabled?: boolean;
16
16
  error?: boolean;
17
- size?: 'medium' | 'small';
17
+ size?: 'medium' | 'small' | 'tiny';
18
18
  placeholder?: string;
19
19
  }
20
20
  export default function Textarea({ id, label, value, onChange, onBlur, onFocus, onKeyDown, onCompositionStart, onCompositionEnd, onSubmit, autoFocus, maxRows, disabled, error, size, placeholder, }: TextareaProps): React.JSX.Element;
@@ -39,6 +39,7 @@ export default function Textarea(_a) {
39
39
  var sizeClasses = {
40
40
  medium: 'text-body1 p-2 leading-[22px]', // body1 (16px), padding 8px
41
41
  small: 'text-body2 p-2 leading-[18px]', // body2 (14px), padding 8px
42
+ tiny: 'text-caption p-1 leading-[16px]', // caption (12px), padding 4px
42
43
  }[size];
43
44
  var baseClasses = 'w-full border rounded-[8px] outline-none [&::-webkit-scrollbar]:hidden';
44
45
  var textColor = 'text-light-text-primary dark:text-dark-text-primary';
@@ -1,12 +1,16 @@
1
1
  'use client';
2
- import React, { useState, useRef, useEffect } from 'react';
2
+ import React, { useState, useRef, useLayoutEffect } from 'react';
3
+ var VIEWPORT_MARGIN = 8;
3
4
  export default function Tooltip(_a) {
4
5
  var title = _a.title, children = _a.children, placement = _a.placement;
5
6
  var _b = useState(false), visible = _b[0], setVisible = _b[1];
6
7
  var _c = useState(placement !== null && placement !== void 0 ? placement : 'bottom'), position = _c[0], setPosition = _c[1];
8
+ var _d = useState(0), shiftX = _d[0], setShiftX = _d[1];
7
9
  var tooltipRef = useRef(null);
8
10
  var buttonRef = useRef(null);
9
- useEffect(function () {
11
+ useLayoutEffect(function () {
12
+ if (!visible)
13
+ return;
10
14
  var handlePosition = function () {
11
15
  if (tooltipRef.current && buttonRef.current) {
12
16
  var tooltipRect = tooltipRef.current.getBoundingClientRect();
@@ -15,18 +19,28 @@ export default function Tooltip(_a) {
15
19
  if (placement) {
16
20
  setPosition(placement);
17
21
  }
18
- else if (window.innerHeight - buttonRect.bottom < tooltipRect.height + 8) {
19
- setPosition('top');
20
- }
21
22
  else {
22
- setPosition('bottom');
23
+ var spaceBelow = window.innerHeight - buttonRect.bottom;
24
+ var fitsBelow = spaceBelow >= tooltipRect.height + VIEWPORT_MARGIN;
25
+ var fitsAbove = buttonRect.top >= tooltipRect.height + VIEWPORT_MARGIN;
26
+ setPosition(!fitsBelow && fitsAbove ? 'top' : 'bottom');
23
27
  }
28
+ // Keep the tooltip inside the viewport horizontally
29
+ var centerX = buttonRect.left + buttonRect.width / 2;
30
+ var half = tooltipRect.width / 2;
31
+ var minCenter = VIEWPORT_MARGIN + half;
32
+ var maxCenter = window.innerWidth - VIEWPORT_MARGIN - half;
33
+ setShiftX(Math.min(Math.max(centerX, minCenter), maxCenter) - centerX);
24
34
  }
25
35
  };
26
- if (visible) {
27
- handlePosition();
28
- }
29
- }, [visible, placement]);
36
+ handlePosition();
37
+ window.addEventListener('resize', handlePosition);
38
+ window.addEventListener('scroll', handlePosition, true);
39
+ return function () {
40
+ window.removeEventListener('resize', handlePosition);
41
+ window.removeEventListener('scroll', handlePosition, true);
42
+ };
43
+ }, [visible, placement, title]);
30
44
  var handleClick = function () {
31
45
  setVisible(false); // Hide tooltip on click
32
46
  };
@@ -36,7 +50,7 @@ export default function Tooltip(_a) {
36
50
  bottom: position === 'top' ? '100%' : undefined,
37
51
  top: position === 'bottom' ? '100%' : undefined,
38
52
  left: '50%',
39
- transform: 'translateX(-50%)',
53
+ transform: "translateX(calc(-50% + ".concat(shiftX, "px))"),
40
54
  }}>
41
55
  {title}
42
56
  </div>)}
@@ -175,13 +175,13 @@ module.exports = {
175
175
  typography: {
176
176
  family: 'Inter, sans-serif',
177
177
  h1: {
178
- weight: '300',
178
+ weight: '400',
179
179
  size: '96px',
180
180
  lineHeight: '120%',
181
181
  letterSpacing: '-1.5px',
182
182
  },
183
183
  h2: {
184
- weight: '300',
184
+ weight: '400',
185
185
  size: '60px',
186
186
  lineHeight: '120%',
187
187
  letterSpacing: '-0.5px',
@@ -205,19 +205,19 @@ module.exports = {
205
205
  letterSpacing: '0px',
206
206
  },
207
207
  h6: {
208
- weight: '500',
208
+ weight: '400',
209
209
  size: '20px',
210
210
  lineHeight: '150%',
211
211
  letterSpacing: '0.2px',
212
212
  },
213
213
  subtitle1: {
214
- weight: '500',
214
+ weight: '400',
215
215
  size: '16px',
216
216
  lineHeight: '150%',
217
217
  letterSpacing: '0.2px',
218
218
  },
219
219
  subtitle2: {
220
- weight: '500',
220
+ weight: '400',
221
221
  size: '14px',
222
222
  lineHeight: '150%',
223
223
  letterSpacing: '0.1px',