@warmio/ui 1.2.0 → 1.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.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # `@warmio/ui`
2
2
 
3
- Portable React components shared by Warm products. Install this package with the exact
4
- `@warmio/design@1.0.0` CSS contract, import `@warmio/design/globals.css` once, and add the package's
5
- compiled files to Tailwind's source detection:
3
+ Portable React components shared by Warm products. Install `@warmio/ui@1.4.0` with the exact
4
+ `@warmio/design@1.6.0` CSS/primitive contract, import `@warmio/design/globals.css` once, and add
5
+ the package's compiled files to Tailwind's source detection:
6
6
 
7
7
  ## Why these files are separate
8
8
 
@@ -19,11 +19,13 @@ deployment permission to publish packages.
19
19
  @source '../node_modules/@warmio/ui/dist';
20
20
  ```
21
21
 
22
- The `1.2.0` public surface contains the Warm badge, logo, Button, Text and `StackedDisplay`,
23
- DropdownMenu, Sheet, the complete responsive Sidebar family, and the `ProductHeader` composition.
24
- `ProductHeader` owns the responsive frame, breadcrumb/title semantics, leading slot, action slot,
25
- and optional portal targets used by Warm product shells. Styling is sealed: use documented semantic
26
- properties and layout wrappers, never `className` or `style` overrides. DropdownMenu interaction
27
- feedback requires the exact public peer `cuelume@0.1.0`.
22
+ The `1.4.0` public UI surface contains the Warm badge, Text and `StackedDisplay`, DropdownMenu,
23
+ Sheet, the complete responsive Sidebar family, and the `ProductHeader` composition. `Button`,
24
+ `ButtonLink`, `Logo`, and `WarmLogoIcon` are directly owned by `@warmio/design@1.6.0` and are
25
+ re-exported through UI where applicable. `ProductHeader` owns the responsive frame,
26
+ breadcrumb/title semantics, leading slot, action slot, and optional portal targets used by Warm
27
+ product shells. Styling is sealed: use documented semantic properties and layout wrappers, never
28
+ `className` or `style` overrides. DropdownMenu interaction feedback requires the exact public peer
29
+ `cuelume@0.1.0`.
28
30
 
29
31
  The published artifact is standalone and never imports private `warm-app` workspace packages.
package/dist/button.js CHANGED
@@ -1,9 +1,7 @@
1
1
  import {
2
2
  Button,
3
3
  ButtonLink
4
- } from "./chunks/chunk-KCEDMF2I.js";
5
- import "./chunks/chunk-T2TXMN3G.js";
6
- import "./chunks/chunk-VIB7OX7D.js";
4
+ } from "./chunks/chunk-GKEYV2XW.js";
7
5
  export {
8
6
  Button,
9
7
  ButtonLink
@@ -6,23 +6,35 @@ import {
6
6
  import * as React from "react";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
8
  var textClassNameByVariant = {
9
- display: "block text-[1.35rem] font-normal leading-snug tracking-normal [font-family:var(--font-display)] @3xl/main:text-[1.875rem]",
9
+ display: "block text-3xl font-normal leading-snug tracking-normal [font-family:var(--font-display)]",
10
10
  displayCompact: "block text-xl font-normal leading-snug tracking-normal [font-family:var(--font-display)] @3xl/main:text-2xl",
11
+ displayHero: "block text-3xl font-bold leading-tight tracking-normal text-foreground sm:text-4xl lg:text-5xl",
12
+ metricValue: "block text-2xl",
13
+ metricValueLead: "block text-3xl",
14
+ metricDisplay: "block text-5xl font-bold leading-none tracking-tight",
15
+ metricDisplayCompact: "block text-4xl font-bold leading-none tracking-tight",
11
16
  overline: "block font-mono text-xs font-bold uppercase tracking-[0.18em]",
12
- micro: "text-[10px] font-normal leading-tight",
13
- microStrong: "text-[10px] font-bold leading-tight",
17
+ micro: "text-xs font-normal leading-snug",
18
+ microStrong: "text-xs font-bold leading-snug",
14
19
  body: "text-sm",
20
+ lede: "text-[1.35rem] leading-snug",
15
21
  caption: "text-xs",
16
22
  helper: "text-xs",
17
- sectionTitle: "text-sm font-bold leading-6"
23
+ sectionTitle: "text-base font-bold leading-normal"
18
24
  };
19
25
  var defaultTextElementByVariant = {
20
26
  display: "span",
21
27
  displayCompact: "span",
28
+ displayHero: "h1",
29
+ metricValue: "span",
30
+ metricValueLead: "span",
31
+ metricDisplay: "span",
32
+ metricDisplayCompact: "span",
22
33
  overline: "span",
23
34
  micro: "span",
24
35
  microStrong: "span",
25
36
  body: "p",
37
+ lede: "p",
26
38
  caption: "span",
27
39
  helper: "small",
28
40
  sectionTitle: "h3"
@@ -33,7 +45,10 @@ var textClassNameByTone = {
33
45
  foreground: "text-foreground",
34
46
  primary: "text-primary",
35
47
  success: "text-success",
36
- warning: "text-warning"
48
+ warning: "text-warning",
49
+ financeCash: "text-finance-cash",
50
+ financeDebt: "text-finance-debt",
51
+ financeInvestment: "text-finance-investment"
37
52
  };
38
53
  var textClassNameByAlign = {
39
54
  start: "text-left",
@@ -42,11 +57,13 @@ var textClassNameByAlign = {
42
57
  };
43
58
  function Text({
44
59
  as,
45
- variant = "micro",
60
+ variant = "caption",
46
61
  tone = "default",
47
62
  align,
48
63
  numeric = false,
64
+ mono = false,
49
65
  truncate = false,
66
+ animateNumber = false,
50
67
  className: _className,
51
68
  style: _style,
52
69
  ...props
@@ -54,11 +71,14 @@ function Text({
54
71
  const Component = as ?? defaultTextElementByVariant[variant];
55
72
  return React.createElement(Component, {
56
73
  ...props,
74
+ "data-animate-number": animateNumber || void 0,
57
75
  className: cn(
58
76
  textClassNameByVariant[variant],
77
+ variant === "sectionTitle" && Component === "h2" && "text-lg leading-snug",
59
78
  textClassNameByTone[tone],
60
79
  align && textClassNameByAlign[align],
61
80
  numeric && "tabular-nums",
81
+ mono && "font-mono",
62
82
  truncate && "truncate"
63
83
  )
64
84
  });
@@ -70,8 +90,8 @@ function StackedDisplay({
70
90
  presentation = "dashboard",
71
91
  secondLine
72
92
  }) {
73
- const firstLineClassName = presentation === "welcome" ? "block text-muted-foreground font-editorial" : "block text-foreground";
74
- const secondLineClassName = presentation === "welcome" ? "block text-foreground" : "block text-muted-foreground font-editorial";
93
+ const firstLineClassName = presentation === "welcome" ? "block text-muted-foreground" : "block text-foreground";
94
+ const secondLineClassName = presentation === "welcome" ? "block text-foreground" : "block text-muted-foreground";
75
95
  return /* @__PURE__ */ jsxs(Text, { as: "span", variant: "displayCompact", align, children: [
76
96
  /* @__PURE__ */ jsx("span", { className: firstLineClassName, children: firstLine }),
77
97
  /* @__PURE__ */ jsx("span", { className: secondLineClassName, children: secondLine })
@@ -1,10 +1,11 @@
1
1
  import {
2
+ Button,
2
3
  Sheet,
3
4
  SheetContent,
4
5
  SheetDescription,
5
6
  SheetHeader,
6
7
  SheetTitle
7
- } from "./chunk-OWDC2VC6.js";
8
+ } from "./chunk-YTDMREDR.js";
8
9
  import {
9
10
  cn
10
11
  } from "./chunk-VIB7OX7D.js";
@@ -76,25 +77,36 @@ function TooltipContent({
76
77
  className,
77
78
  side = "top",
78
79
  align = "center",
79
- sideOffset = 0,
80
+ alignOffset = 0,
81
+ sideOffset = 4,
80
82
  children,
81
83
  ...props
82
84
  }) {
83
- return /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(TooltipPrimitive.Positioner, { side, align, sideOffset, children: /* @__PURE__ */ jsxs(
84
- TooltipPrimitive.Popup,
85
+ return /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(
86
+ TooltipPrimitive.Positioner,
85
87
  {
86
- "data-slot": "tooltip-content",
87
- className: cn(
88
- "z-[var(--z-popover)] inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-lg bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-[calc(var(--z-popover)+1)] **:data-[slot=kbd]:rounded-lg data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
89
- className
90
- ),
91
- ...props,
92
- children: [
93
- children,
94
- /* @__PURE__ */ jsx(TooltipPrimitive.Arrow, { className: "z-[calc(var(--z-popover)+1)] size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-lg bg-foreground fill-foreground" })
95
- ]
88
+ side,
89
+ align,
90
+ alignOffset,
91
+ sideOffset,
92
+ className: "isolate z-[var(--z-popover)]",
93
+ children: /* @__PURE__ */ jsxs(
94
+ TooltipPrimitive.Popup,
95
+ {
96
+ "data-slot": "tooltip-content",
97
+ className: cn(
98
+ "z-[var(--z-popover)] inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-lg bg-popover px-3 py-1.5 text-xs text-popover-foreground shadow-md ring-1 ring-foreground/10 has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-[calc(var(--z-popover)+1)] **:data-[slot=kbd]:rounded-lg data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
99
+ className
100
+ ),
101
+ ...props,
102
+ children: [
103
+ children,
104
+ /* @__PURE__ */ jsx(TooltipPrimitive.Arrow, { className: "z-[calc(var(--z-popover)+1)] size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-lg bg-popover fill-popover data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" })
105
+ ]
106
+ }
107
+ )
96
108
  }
97
- ) }) });
109
+ ) });
98
110
  }
99
111
 
100
112
  // ../ui/src/components/sidebar.tsx
@@ -102,6 +114,11 @@ import { MenuIcon, PanelLeftIcon } from "lucide-react";
102
114
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
103
115
  var SIDEBAR_COOKIE_NAME = "sidebar_state";
104
116
  var SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
117
+ function readSidebarCookie(cookie) {
118
+ const match = cookie.match(/(?:^|; )sidebar_state=(true|false)(?:;|$)/);
119
+ if (!match) return null;
120
+ return match[1] === "true";
121
+ }
105
122
  var SIDEBAR_KEYBOARD_SHORTCUT = "b";
106
123
  var TABLET_ICON_SIDEBAR_QUERY = "(min-width: 768px) and (max-width: 1279px)";
107
124
  var getServerForceIconSidebarSnapshot = () => false;
@@ -113,24 +130,21 @@ function useSidebar() {
113
130
  }
114
131
  return context;
115
132
  }
133
+ function subscribeToForceIconSidebar(onStoreChange) {
134
+ const mql = window.matchMedia(TABLET_ICON_SIDEBAR_QUERY);
135
+ mql.addEventListener("change", onStoreChange);
136
+ return () => mql.removeEventListener("change", onStoreChange);
137
+ }
138
+ function getForceIconSidebarSnapshot() {
139
+ return window.matchMedia(TABLET_ICON_SIDEBAR_QUERY).matches;
140
+ }
116
141
  function useForceIconSidebar(forceIconAtTablet) {
117
- return React4.useSyncExternalStore(
118
- React4.useCallback(
119
- (onStoreChange) => {
120
- if (!forceIconAtTablet) return () => {
121
- };
122
- const mql = window.matchMedia(TABLET_ICON_SIDEBAR_QUERY);
123
- mql.addEventListener("change", onStoreChange);
124
- return () => mql.removeEventListener("change", onStoreChange);
125
- },
126
- [forceIconAtTablet]
127
- ),
128
- React4.useCallback(() => {
129
- if (!forceIconAtTablet) return false;
130
- return window.matchMedia(TABLET_ICON_SIDEBAR_QUERY).matches;
131
- }, [forceIconAtTablet]),
142
+ const isTablet = React4.useSyncExternalStore(
143
+ subscribeToForceIconSidebar,
144
+ getForceIconSidebarSnapshot,
132
145
  getServerForceIconSidebarSnapshot
133
146
  );
147
+ return forceIconAtTablet && isTablet;
134
148
  }
135
149
  function SidebarProvider({
136
150
  defaultOpen = true,
@@ -146,17 +160,24 @@ function SidebarProvider({
146
160
  const isMobile = useIsMobile();
147
161
  const forceIcon = useForceIconSidebar(forceIconAtTablet);
148
162
  const [openMobile, setOpenMobile] = React4.useState(false);
163
+ const [sidebarMotionEnabled, setSidebarMotionEnabled] = React4.useState(false);
149
164
  const [_open, _setOpen] = React4.useReducer(
150
165
  (_, nextOpen) => nextOpen,
151
166
  defaultOpen
152
167
  );
168
+ const cookieHydratedRef = React4.useRef(false);
169
+ const hydrateSidebarCookie = (node) => {
170
+ if (!node || cookieHydratedRef.current) return;
171
+ cookieHydratedRef.current = true;
172
+ const stored = readSidebarCookie(document.cookie);
173
+ if (stored !== null) _setOpen(stored);
174
+ };
153
175
  const open = openProp ?? _open;
154
176
  const setOpen = React4.useCallback(
155
- (value) => {
177
+ (openState) => {
156
178
  if (!allowUserCollapse) {
157
179
  return;
158
180
  }
159
- const openState = typeof value === "function" ? value(open) : value;
160
181
  if (setOpenProp) {
161
182
  setOpenProp(openState);
162
183
  } else {
@@ -164,15 +185,30 @@ function SidebarProvider({
164
185
  }
165
186
  document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
166
187
  },
167
- [allowUserCollapse, setOpenProp, open]
188
+ [allowUserCollapse, setOpenProp]
168
189
  );
169
190
  const toggleSidebar = React4.useCallback(() => {
170
191
  if (!allowUserCollapse) {
171
192
  return;
172
193
  }
173
- return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
174
- }, [allowUserCollapse, isMobile, setOpen, setOpenMobile]);
194
+ setSidebarMotionEnabled(true);
195
+ return isMobile ? setOpenMobile((open2) => !open2) : setOpen(!open);
196
+ }, [allowUserCollapse, isMobile, open, setOpen]);
175
197
  const toggleSidebarEvent = React4.useEffectEvent(toggleSidebar);
198
+ const state = forceIcon && !isMobile ? "collapsed" : open ? "expanded" : "collapsed";
199
+ const contextValue = React4.useMemo(
200
+ () => ({
201
+ state,
202
+ open,
203
+ setOpen,
204
+ isMobile,
205
+ openMobile,
206
+ setOpenMobile,
207
+ toggleSidebar,
208
+ sidebarMotionEnabled
209
+ }),
210
+ [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar, sidebarMotionEnabled]
211
+ );
176
212
  React4.useEffect(() => {
177
213
  if (!allowUserCollapse) {
178
214
  return;
@@ -186,22 +222,10 @@ function SidebarProvider({
186
222
  window.addEventListener("keydown", handleKeyDown);
187
223
  return () => window.removeEventListener("keydown", handleKeyDown);
188
224
  }, [allowUserCollapse]);
189
- const state = forceIcon && !isMobile ? "collapsed" : open ? "expanded" : "collapsed";
190
- const contextValue = React4.useMemo(
191
- () => ({
192
- state,
193
- open,
194
- setOpen,
195
- isMobile,
196
- openMobile,
197
- setOpenMobile,
198
- toggleSidebar
199
- }),
200
- [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
201
- );
202
225
  return /* @__PURE__ */ jsx2(SidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx2(
203
226
  "div",
204
227
  {
228
+ ref: hydrateSidebarCookie,
205
229
  "data-slot": "sidebar-wrapper",
206
230
  style,
207
231
  className: cn(
@@ -222,7 +246,9 @@ function Sidebar({
222
246
  dir,
223
247
  ...props
224
248
  }) {
225
- const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
249
+ const { isMobile, state, openMobile, setOpenMobile, sidebarMotionEnabled } = useSidebar();
250
+ const sidebarWidthMotionClassName = sidebarMotionEnabled ? "transition-[width] duration-300 ease-linear motion-reduce:transition-none" : null;
251
+ const sidebarPositionMotionClassName = sidebarMotionEnabled ? "transition-[left,right,width] duration-300 ease-linear motion-reduce:transition-none" : null;
226
252
  if (collapsible === "none") {
227
253
  return /* @__PURE__ */ jsx2(
228
254
  "div",
@@ -272,7 +298,8 @@ function Sidebar({
272
298
  {
273
299
  "data-slot": "sidebar-gap",
274
300
  className: cn(
275
- "relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear",
301
+ "relative w-(--sidebar-width) bg-transparent",
302
+ sidebarWidthMotionClassName,
276
303
  "group-data-[collapsible=offcanvas]:w-0",
277
304
  "group-data-[side=right]:rotate-180",
278
305
  variant === "floating" || variant === "inset" ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
@@ -285,7 +312,8 @@ function Sidebar({
285
312
  "data-slot": "sidebar-container",
286
313
  "data-side": side,
287
314
  className: cn(
288
- "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear data-[side=left]:left-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:right-0 data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)] md:flex",
315
+ "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) data-[side=left]:left-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:right-0 data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)] md:flex",
316
+ sidebarPositionMotionClassName,
289
317
  // Adjust the padding for floating and inset variants.
290
318
  variant === "floating" || variant === "inset" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
291
319
  className
@@ -306,13 +334,35 @@ function Sidebar({
306
334
  }
307
335
  );
308
336
  }
337
+ function SidebarTrigger({ className, onClick, ...props }) {
338
+ const { isMobile, toggleSidebar } = useSidebar();
339
+ return /* @__PURE__ */ jsxs2(
340
+ Button,
341
+ {
342
+ "data-sidebar": "trigger",
343
+ "data-slot": "sidebar-trigger",
344
+ variant: "ghost",
345
+ size: "icon-sm",
346
+ className: cn(className),
347
+ onClick: (event) => {
348
+ onClick?.(event);
349
+ toggleSidebar();
350
+ },
351
+ ...props,
352
+ children: [
353
+ isMobile ? /* @__PURE__ */ jsx2(MenuIcon, {}) : /* @__PURE__ */ jsx2(PanelLeftIcon, {}),
354
+ /* @__PURE__ */ jsx2("span", { className: "sr-only", children: "Toggle Sidebar" })
355
+ ]
356
+ }
357
+ );
358
+ }
309
359
  function SidebarInset({ className, ...props }) {
310
360
  return /* @__PURE__ */ jsx2(
311
361
  "main",
312
362
  {
313
363
  "data-slot": "sidebar-inset",
314
364
  className: cn(
315
- "relative flex w-full flex-1 flex-col bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2",
365
+ "relative flex min-h-0 w-full flex-1 flex-col bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2",
316
366
  className
317
367
  ),
318
368
  ...props
@@ -381,7 +431,7 @@ function SidebarGroupLabel({
381
431
  "data-slot": "sidebar-group-label",
382
432
  "data-sidebar": "group-label",
383
433
  className: cn(
384
- "flex h-8 shrink-0 items-center rounded-lg px-2 text-xs font-bold text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
434
+ "flex h-8 shrink-0 items-center rounded-lg px-2 text-xs font-bold text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:mt-0 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
385
435
  className
386
436
  ),
387
437
  ...props
@@ -400,14 +450,10 @@ function SidebarGroupContent({ className, ...props }) {
400
450
  );
401
451
  }
402
452
  var sidebarMenuSpacingClassName = {
403
- default: "gap-1",
453
+ default: "gap-2",
404
454
  roomy: "gap-2"
405
455
  };
406
- function SidebarMenu({
407
- className,
408
- spacing = "default",
409
- ...props
410
- }) {
456
+ function SidebarMenu({ className, spacing = "default", ...props }) {
411
457
  return /* @__PURE__ */ jsx2(
412
458
  "ul",
413
459
  {
@@ -434,7 +480,7 @@ function SidebarMenuItem({ className, ...props }) {
434
480
  );
435
481
  }
436
482
  var sidebarMenuButtonVariants = cva(
437
- "peer/menu-button group/menu-button flex w-full items-center gap-2 overflow-hidden rounded-lg p-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 focus-visible:ring-inset active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:font-bold data-active:text-sidebar-accent-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate",
483
+ "peer/menu-button group/menu-button flex w-full items-center gap-2 overflow-hidden rounded-lg p-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-4 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 focus-visible:ring-inset active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:font-bold data-active:text-sidebar-accent-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate",
438
484
  {
439
485
  variants: {
440
486
  variant: {
@@ -506,7 +552,7 @@ function SidebarMenuBadge({ className, ...props }) {
506
552
  "data-slot": "sidebar-menu-badge",
507
553
  "data-sidebar": "menu-badge",
508
554
  className: cn(
509
- "pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-lg px-1 text-xs font-bold text-sidebar-foreground tabular-nums select-none group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 peer-data-active/menu-button:text-sidebar-accent-foreground",
555
+ "pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-lg px-2 text-xs font-bold text-sidebar-foreground tabular-nums select-none group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 peer-data-active/menu-button:text-sidebar-accent-foreground",
510
556
  className
511
557
  ),
512
558
  ...props
@@ -526,15 +572,15 @@ function SidebarBrand({ actions, collapsed, expanded }) {
526
572
  React5.cloneElement(collapsed, {
527
573
  className: "hidden size-8 shrink-0 items-center justify-center rounded-lg text-sidebar-foreground transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 focus-visible:ring-sidebar-ring focus-visible:outline-hidden group-data-[collapsible=icon]:flex"
528
574
  }),
529
- actions ? /* @__PURE__ */ jsx3("div", { className: "flex items-center gap-1 group-data-[collapsible=icon]:hidden", children: actions }) : null
575
+ actions ? /* @__PURE__ */ jsx3("div", { className: "flex items-center gap-2 group-data-[collapsible=icon]:hidden", children: actions }) : null
530
576
  ] });
531
577
  }
532
578
  var SidebarAccountTrigger = React5.forwardRef(function SidebarAccountTrigger2({ avatar, className: _className, email, label, style: _style, ...props }, ref) {
533
579
  return /* @__PURE__ */ jsxs3(SidebarMenuButton2, { ...props, ref, presentation: "account", children: [
534
- /* @__PURE__ */ jsx3("div", { className: "grid size-8 shrink-0 place-items-center rounded-lg bg-sidebar-primary text-xs font-bold text-sidebar-primary-foreground", children: avatar ?? /* @__PURE__ */ jsx3(UserRound, { className: "size-4", "aria-hidden": "true" }) }),
580
+ /* @__PURE__ */ jsx3("div", { className: "grid size-8 shrink-0 place-items-center rounded-lg bg-sidebar-primary text-xs font-bold text-sidebar-primary-foreground group-data-[collapsible=icon]:size-8 group-data-[collapsible=icon]:rounded-full", children: avatar ?? /* @__PURE__ */ jsx3(UserRound, { className: "size-4", "aria-hidden": "true" }) }),
535
581
  /* @__PURE__ */ jsxs3("div", { className: "min-w-0 flex-1 text-left group-data-[collapsible=icon]:hidden", children: [
536
- /* @__PURE__ */ jsx3("div", { className: "truncate text-sm font-bold", children: label }),
537
- /* @__PURE__ */ jsx3("div", { className: "truncate text-xs text-sidebar-foreground/60", children: email })
582
+ /* @__PURE__ */ jsx3("div", { className: "truncate text-sm font-bold", title: label, children: label }),
583
+ /* @__PURE__ */ jsx3("div", { className: "truncate text-xs text-sidebar-foreground/60", title: email, children: email })
538
584
  ] }),
539
585
  /* @__PURE__ */ jsx3(ChevronUp, { className: "ml-auto size-4 group-data-[collapsible=icon]:hidden" })
540
586
  ] });
@@ -549,7 +595,7 @@ function SidebarProvider2({
549
595
  style: _style,
550
596
  ...props
551
597
  }) {
552
- const presentationClassName = presentation === "mockup" ? "min-h-0" : presentation === "preview" ? "min-h-full" : void 0;
598
+ const presentationClassName = presentation === "mockup" ? "min-h-0 [--sidebar-width:16rem]" : presentation === "preview" ? "min-h-full" : void 0;
553
599
  return /* @__PURE__ */ jsx4(SidebarProvider, { ...props, className: presentationClassName });
554
600
  }
555
601
  function Sidebar2({
@@ -589,7 +635,7 @@ function SidebarContent2({
589
635
  style: _style,
590
636
  ...props
591
637
  }) {
592
- const className = presentation === "product" ? "pb-0" : presentation === "mockup" ? "px-1 py-3" : void 0;
638
+ const className = presentation === "product" ? "pb-0" : presentation === "mockup" ? "px-2 py-4" : void 0;
593
639
  return /* @__PURE__ */ jsx4(SidebarContent, { ...props, className });
594
640
  }
595
641
  function SidebarFooter2({
@@ -608,7 +654,7 @@ function SidebarGroup2({
608
654
  style: _style,
609
655
  ...props
610
656
  }) {
611
- const className = presentation === "navigation" || presentation === "navigation-primary" ? `${collapsed ? "items-center " : ""}${presentation === "navigation-primary" ? "px-2 pt-3 pb-1" : "px-2 py-1"}` : presentation === "mockup" ? "py-1" : void 0;
657
+ const className = presentation === "navigation" || presentation === "navigation-primary" ? `${collapsed ? "items-center " : ""}${presentation === "navigation-primary" ? "px-2 pt-4 pb-2" : "px-2 py-2"}` : presentation === "mockup" ? "py-2" : void 0;
612
658
  return /* @__PURE__ */ jsx4(SidebarGroup, { ...props, className });
613
659
  }
614
660
  function SidebarGroupContent2({
@@ -647,8 +693,8 @@ var SidebarMenuButton2 = React6.forwardRef(
647
693
  ref,
648
694
  className: cn(
649
695
  (collapsed || presentation === "previewCollapsed") && "mx-auto size-8 gap-0 p-2",
650
- presentation === "account" && "h-12",
651
- presentation === "navigation" && "[&>span:last-child]:text-sidebar-foreground/50 [&>span:last-child]:transition-colors hover:[&>span:last-child]:text-sidebar-accent-foreground data-active:[&>span:last-child]:text-sidebar-accent-foreground",
696
+ presentation === "account" && "h-12 group-data-[collapsible=icon]:mx-auto group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:justify-center group-data-[collapsible=icon]:gap-0! group-data-[collapsible=icon]:p-0!",
697
+ presentation === "navigation" && "text-sidebar-foreground hover:text-sidebar-foreground active:text-sidebar-foreground data-open:hover:text-sidebar-foreground data-active:text-sidebar-foreground",
652
698
  (disabled || presentation === "disabled") && "text-muted-foreground/60"
653
699
  )
654
700
  }
@@ -666,10 +712,20 @@ function SidebarMenuBadge2({
666
712
  SidebarMenuBadge,
667
713
  {
668
714
  ...props,
669
- className: presentation === "attention" ? "animate-pulse" : void 0
715
+ className: cn(
716
+ "text-sidebar-foreground peer-hover/menu-button:text-sidebar-foreground peer-data-active/menu-button:text-sidebar-foreground",
717
+ presentation === "attention" && "animate-pulse"
718
+ )
670
719
  }
671
720
  );
672
721
  }
722
+ function SidebarTrigger2({
723
+ className: _className,
724
+ style: _style,
725
+ ...props
726
+ }) {
727
+ return /* @__PURE__ */ jsx4(SidebarTrigger, { ...props });
728
+ }
673
729
 
674
730
  export {
675
731
  useSidebar,
@@ -687,5 +743,6 @@ export {
687
743
  SidebarMenu2 as SidebarMenu,
688
744
  SidebarMenuItem2 as SidebarMenuItem,
689
745
  SidebarMenuButton2 as SidebarMenuButton,
690
- SidebarMenuBadge2 as SidebarMenuBadge
746
+ SidebarMenuBadge2 as SidebarMenuBadge,
747
+ SidebarTrigger2 as SidebarTrigger
691
748
  };
@@ -0,0 +1,10 @@
1
+ // ../ui/src/warmio/button.tsx
2
+ import {
3
+ Button,
4
+ ButtonLink
5
+ } from "@warmio/design/button";
6
+
7
+ export {
8
+ Button,
9
+ ButtonLink
10
+ };