@warmio/ui 1.0.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 ADDED
@@ -0,0 +1,13 @@
1
+ # `@warmio/ui`
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:
6
+
7
+ ```css
8
+ @import '@warmio/design/globals.css';
9
+ @source '../node_modules/@warmio/ui/dist';
10
+ ```
11
+
12
+ The initial public surface contains the Warm badge, logo, and complete responsive sidebar family.
13
+ The published artifact is standalone and never imports private `warm-app` workspace packages.
package/dist/badge.js ADDED
@@ -0,0 +1,7 @@
1
+ import {
2
+ Badge
3
+ } from "./chunks/chunk-ICC7GQXS.js";
4
+ import "./chunks/chunk-VIB7OX7D.js";
5
+ export {
6
+ Badge
7
+ };
@@ -0,0 +1,803 @@
1
+ import {
2
+ cn
3
+ } from "./chunk-VIB7OX7D.js";
4
+
5
+ // ../ui/src/components/sidebar.tsx
6
+ import * as React6 from "react";
7
+ import { cva as cva2 } from "class-variance-authority";
8
+
9
+ // ../ui/src/hooks/use-mobile.ts
10
+ import * as React from "react";
11
+ var MOBILE_BREAKPOINT = 768;
12
+ function getIsMobileSnapshot() {
13
+ return window.innerWidth < MOBILE_BREAKPOINT;
14
+ }
15
+ function getServerIsMobileSnapshot() {
16
+ return false;
17
+ }
18
+ function subscribeToMobileChanges(onStoreChange) {
19
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
20
+ mql.addEventListener("change", onStoreChange);
21
+ return () => mql.removeEventListener("change", onStoreChange);
22
+ }
23
+ function useIsMobile() {
24
+ return React.useSyncExternalStore(
25
+ subscribeToMobileChanges,
26
+ getIsMobileSnapshot,
27
+ getServerIsMobileSnapshot
28
+ );
29
+ }
30
+
31
+ // ../ui/src/lib/render-slot.tsx
32
+ import * as React2 from "react";
33
+ import { useRender } from "@base-ui/react/use-render";
34
+ function RenderSlot({
35
+ asChild = false,
36
+ children,
37
+ defaultTagName,
38
+ render,
39
+ ref,
40
+ ...props
41
+ }) {
42
+ const resolvedRender = render ?? (asChild && React2.isValidElement(children) ? children : void 0);
43
+ return useRender({
44
+ defaultTagName,
45
+ render: resolvedRender,
46
+ ref,
47
+ props: {
48
+ ...props,
49
+ children: resolvedRender ? void 0 : children
50
+ }
51
+ });
52
+ }
53
+
54
+ // ../ui/src/components/button.tsx
55
+ import * as React3 from "react";
56
+ import { Button as ButtonPrimitive } from "@base-ui/react/button";
57
+
58
+ // ../ui/src/components/button.variants.ts
59
+ import { cva } from "class-variance-authority";
60
+ var buttonVariants = cva(
61
+ "group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-inset focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-inset aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
62
+ {
63
+ variants: {
64
+ variant: {
65
+ default: "border-[color:var(--button-primary-border)] bg-[var(--button-primary-bg)] bg-[image:var(--button-primary-gradient)] text-[color:var(--button-primary-foreground)] shadow-[var(--button-primary-shadow)] hover:bg-[var(--button-primary-hover)] active:bg-[var(--button-primary-active)]",
66
+ outline: "border-border bg-background shadow-xs hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
67
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
68
+ ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
69
+ destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
70
+ link: "underline-offset-4 decoration-current hover:underline"
71
+ },
72
+ size: {
73
+ default: "h-9 gap-2 rounded-lg px-3 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5",
74
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
75
+ sm: "h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5",
76
+ md: "h-9 gap-2 rounded-lg px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5",
77
+ lg: "h-11 gap-2 rounded-xl px-5 text-base has-data-[icon=inline-end]:pr-4 has-data-[icon=inline-start]:pl-4",
78
+ xl: "h-12 gap-2 rounded-xl px-6 text-base has-data-[icon=inline-end]:pr-5 has-data-[icon=inline-start]:pl-5",
79
+ option: "h-auto min-h-16 items-start justify-start gap-2 whitespace-normal rounded-xl px-3 py-3 text-sm",
80
+ icon: "size-9",
81
+ "icon-round": "size-9 rounded-full",
82
+ "icon-xs": "size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3",
83
+ "icon-sm": "size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md",
84
+ "icon-lg": "size-10",
85
+ "icon-xl": "size-11 rounded-lg",
86
+ "input-icon": "h-full w-10 rounded-l-none"
87
+ }
88
+ },
89
+ defaultVariants: {
90
+ variant: "default",
91
+ size: "default"
92
+ }
93
+ }
94
+ );
95
+
96
+ // ../ui/src/components/button.tsx
97
+ import { jsx } from "react/jsx-runtime";
98
+ function Button({
99
+ className,
100
+ variant = "default",
101
+ size = "default",
102
+ asChild = false,
103
+ render,
104
+ children,
105
+ ...props
106
+ }) {
107
+ const resolvedRender = render ?? (asChild && React3.isValidElement(children) ? children : void 0);
108
+ return /* @__PURE__ */ jsx(
109
+ ButtonPrimitive,
110
+ {
111
+ "data-slot": "button",
112
+ "data-variant": variant,
113
+ "data-size": size,
114
+ className: cn(buttonVariants({ variant, size }), className),
115
+ ...props,
116
+ render: resolvedRender,
117
+ children: resolvedRender ? void 0 : children
118
+ }
119
+ );
120
+ }
121
+
122
+ // ../ui/src/components/sheet.tsx
123
+ import * as React4 from "react";
124
+ import { Dialog as SheetPrimitive } from "@base-ui/react/dialog";
125
+ import { XIcon } from "lucide-react";
126
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
127
+ function Sheet(props) {
128
+ return /* @__PURE__ */ jsx2(SheetPrimitive.Root, { ...props });
129
+ }
130
+ function SheetPortal({ ...props }) {
131
+ return /* @__PURE__ */ jsx2(SheetPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
132
+ }
133
+ function SheetOverlay({ className, ...props }) {
134
+ return /* @__PURE__ */ jsx2(
135
+ SheetPrimitive.Backdrop,
136
+ {
137
+ "data-slot": "sheet-overlay",
138
+ className: cn(
139
+ "fixed inset-0 z-[var(--z-overlay-backdrop)] bg-black/20 duration-100 supports-backdrop-filter:backdrop-blur data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
140
+ className
141
+ ),
142
+ ...props
143
+ }
144
+ );
145
+ }
146
+ function SheetContent({
147
+ className,
148
+ children,
149
+ side = "right",
150
+ showCloseButton = true,
151
+ overlayClassName,
152
+ ...props
153
+ }) {
154
+ return /* @__PURE__ */ jsxs(SheetPortal, { children: [
155
+ /* @__PURE__ */ jsx2(SheetOverlay, { className: overlayClassName }),
156
+ /* @__PURE__ */ jsxs(
157
+ SheetPrimitive.Popup,
158
+ {
159
+ "data-slot": "sheet-content",
160
+ "data-side": side,
161
+ className: cn(
162
+ "fixed z-[calc(var(--z-overlay-backdrop)+1)] flex flex-col gap-4 bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:max-h-[calc(100dvh-var(--safe-area-inset-top)-var(--safe-area-inset-bottom))] data-[side=bottom]:overflow-y-auto data-[side=bottom]:border-t data-[side=bottom]:pb-[var(--safe-area-inset-bottom)] data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=left]:pt-[var(--safe-area-inset-top)] data-[side=left]:pb-[var(--safe-area-inset-bottom)] data-[side=left]:pl-[var(--safe-area-inset-left)] data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=right]:pt-[var(--safe-area-inset-top)] data-[side=right]:pr-[var(--safe-area-inset-right)] data-[side=right]:pb-[var(--safe-area-inset-bottom)] data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:max-h-[calc(100dvh-var(--safe-area-inset-top)-var(--safe-area-inset-bottom))] data-[side=top]:overflow-y-auto data-[side=top]:border-b data-[side=top]:pt-[var(--safe-area-inset-top)] data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-[side=bottom]:data-open:slide-in-from-bottom-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:animate-out data-closed:fade-out-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=right]:data-closed:slide-out-to-right-10 data-[side=top]:data-closed:slide-out-to-top-10 motion-reduce:animate-none motion-reduce:transition-none",
163
+ className
164
+ ),
165
+ ...props,
166
+ children: [
167
+ children,
168
+ showCloseButton && /* @__PURE__ */ jsxs(
169
+ SheetPrimitive.Close,
170
+ {
171
+ "data-slot": "sheet-close",
172
+ render: /* @__PURE__ */ jsx2(
173
+ Button,
174
+ {
175
+ variant: "ghost",
176
+ className: "absolute top-[max(1rem,var(--safe-area-inset-top))] right-[max(1rem,var(--safe-area-inset-right))]",
177
+ size: "icon-sm"
178
+ }
179
+ ),
180
+ children: [
181
+ /* @__PURE__ */ jsx2(XIcon, {}),
182
+ /* @__PURE__ */ jsx2("span", { className: "sr-only", children: "Close" })
183
+ ]
184
+ }
185
+ )
186
+ ]
187
+ }
188
+ )
189
+ ] });
190
+ }
191
+ function SheetHeader({ className, ...props }) {
192
+ return /* @__PURE__ */ jsx2(
193
+ "div",
194
+ {
195
+ "data-slot": "sheet-header",
196
+ className: cn("flex flex-col gap-1.5 p-4", className),
197
+ ...props
198
+ }
199
+ );
200
+ }
201
+ function SheetTitle({ className, ...props }) {
202
+ return /* @__PURE__ */ jsx2(
203
+ SheetPrimitive.Title,
204
+ {
205
+ "data-slot": "sheet-title",
206
+ className: cn("font-heading font-bold text-foreground", className),
207
+ ...props
208
+ }
209
+ );
210
+ }
211
+ function SheetDescription({ className, ...props }) {
212
+ return /* @__PURE__ */ jsx2(
213
+ SheetPrimitive.Description,
214
+ {
215
+ "data-slot": "sheet-description",
216
+ className: cn("text-sm text-muted-foreground", className),
217
+ ...props
218
+ }
219
+ );
220
+ }
221
+
222
+ // ../ui/src/components/tooltip.tsx
223
+ import * as React5 from "react";
224
+ import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";
225
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
226
+ function Tooltip(props) {
227
+ return /* @__PURE__ */ jsx3(TooltipPrimitive.Root, { ...props });
228
+ }
229
+ function TooltipTrigger({ asChild = false, children, render, ...props }) {
230
+ const resolvedRender = render ?? (asChild && React5.isValidElement(children) ? children : void 0);
231
+ return /* @__PURE__ */ jsx3(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", render: resolvedRender, ...props, children: resolvedRender ? void 0 : children });
232
+ }
233
+ function TooltipContent({
234
+ className,
235
+ side = "top",
236
+ align = "center",
237
+ sideOffset = 0,
238
+ children,
239
+ ...props
240
+ }) {
241
+ return /* @__PURE__ */ jsx3(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx3(TooltipPrimitive.Positioner, { side, align, sideOffset, children: /* @__PURE__ */ jsxs2(
242
+ TooltipPrimitive.Popup,
243
+ {
244
+ "data-slot": "tooltip-content",
245
+ className: cn(
246
+ "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",
247
+ className
248
+ ),
249
+ ...props,
250
+ children: [
251
+ children,
252
+ /* @__PURE__ */ jsx3(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" })
253
+ ]
254
+ }
255
+ ) }) });
256
+ }
257
+
258
+ // ../ui/src/components/sidebar.tsx
259
+ import { MenuIcon, PanelLeftIcon } from "lucide-react";
260
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
261
+ var SIDEBAR_COOKIE_NAME = "sidebar_state";
262
+ var SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
263
+ var SIDEBAR_KEYBOARD_SHORTCUT = "b";
264
+ var TABLET_ICON_SIDEBAR_QUERY = "(min-width: 768px) and (max-width: 1279px)";
265
+ var getServerForceIconSidebarSnapshot = () => false;
266
+ var SidebarContext = React6.createContext(null);
267
+ function useSidebar() {
268
+ const context = React6.use(SidebarContext);
269
+ if (!context) {
270
+ throw new Error("useSidebar must be used within a SidebarProvider.");
271
+ }
272
+ return context;
273
+ }
274
+ function useForceIconSidebar(forceIconAtTablet) {
275
+ return React6.useSyncExternalStore(
276
+ React6.useCallback(
277
+ (onStoreChange) => {
278
+ if (!forceIconAtTablet) return () => {
279
+ };
280
+ const mql = window.matchMedia(TABLET_ICON_SIDEBAR_QUERY);
281
+ mql.addEventListener("change", onStoreChange);
282
+ return () => mql.removeEventListener("change", onStoreChange);
283
+ },
284
+ [forceIconAtTablet]
285
+ ),
286
+ React6.useCallback(() => {
287
+ if (!forceIconAtTablet) return false;
288
+ return window.matchMedia(TABLET_ICON_SIDEBAR_QUERY).matches;
289
+ }, [forceIconAtTablet]),
290
+ getServerForceIconSidebarSnapshot
291
+ );
292
+ }
293
+ function SidebarProvider({
294
+ defaultOpen = true,
295
+ open: openProp,
296
+ onOpenChange: setOpenProp,
297
+ className,
298
+ style,
299
+ forceIconAtTablet = false,
300
+ allowUserCollapse = true,
301
+ children,
302
+ ...props
303
+ }) {
304
+ const isMobile = useIsMobile();
305
+ const forceIcon = useForceIconSidebar(forceIconAtTablet);
306
+ const [openMobile, setOpenMobile] = React6.useState(false);
307
+ const [_open, _setOpen] = React6.useReducer(
308
+ (_, nextOpen) => nextOpen,
309
+ defaultOpen
310
+ );
311
+ const open = openProp ?? _open;
312
+ const setOpen = React6.useCallback(
313
+ (value) => {
314
+ if (!allowUserCollapse) {
315
+ return;
316
+ }
317
+ const openState = typeof value === "function" ? value(open) : value;
318
+ if (setOpenProp) {
319
+ setOpenProp(openState);
320
+ } else {
321
+ _setOpen(openState);
322
+ }
323
+ document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
324
+ },
325
+ [allowUserCollapse, setOpenProp, open]
326
+ );
327
+ const toggleSidebar = React6.useCallback(() => {
328
+ if (!allowUserCollapse) {
329
+ return;
330
+ }
331
+ return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
332
+ }, [allowUserCollapse, isMobile, setOpen, setOpenMobile]);
333
+ const toggleSidebarEvent = React6.useEffectEvent(toggleSidebar);
334
+ React6.useEffect(() => {
335
+ if (!allowUserCollapse) {
336
+ return;
337
+ }
338
+ const handleKeyDown = (event) => {
339
+ if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
340
+ event.preventDefault();
341
+ toggleSidebarEvent();
342
+ }
343
+ };
344
+ window.addEventListener("keydown", handleKeyDown);
345
+ return () => window.removeEventListener("keydown", handleKeyDown);
346
+ }, [allowUserCollapse]);
347
+ const state = forceIcon && !isMobile ? "collapsed" : open ? "expanded" : "collapsed";
348
+ const contextValue = React6.useMemo(
349
+ () => ({
350
+ state,
351
+ open,
352
+ setOpen,
353
+ isMobile,
354
+ openMobile,
355
+ setOpenMobile,
356
+ toggleSidebar
357
+ }),
358
+ [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
359
+ );
360
+ return /* @__PURE__ */ jsx4(SidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx4(
361
+ "div",
362
+ {
363
+ "data-slot": "sidebar-wrapper",
364
+ style,
365
+ className: cn(
366
+ "group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar",
367
+ className
368
+ ),
369
+ ...props,
370
+ children
371
+ }
372
+ ) });
373
+ }
374
+ function Sidebar({
375
+ side = "left",
376
+ variant = "sidebar",
377
+ collapsible = "offcanvas",
378
+ className,
379
+ children,
380
+ dir,
381
+ ...props
382
+ }) {
383
+ const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
384
+ if (collapsible === "none") {
385
+ return /* @__PURE__ */ jsx4(
386
+ "div",
387
+ {
388
+ "data-slot": "sidebar",
389
+ className: cn(
390
+ "flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground",
391
+ className
392
+ ),
393
+ ...props,
394
+ children
395
+ }
396
+ );
397
+ }
398
+ if (isMobile) {
399
+ return /* @__PURE__ */ jsx4(Sheet, { open: openMobile, onOpenChange: setOpenMobile, ...props, children: /* @__PURE__ */ jsxs3(
400
+ SheetContent,
401
+ {
402
+ dir,
403
+ "data-sidebar": "sidebar",
404
+ "data-slot": "sidebar",
405
+ "data-mobile": "true",
406
+ className: "w-[var(--sidebar-width-mobile)] bg-sidebar p-0 text-sidebar-foreground dark:bg-card [&>button]:hidden",
407
+ side,
408
+ children: [
409
+ /* @__PURE__ */ jsxs3(SheetHeader, { className: "sr-only", children: [
410
+ /* @__PURE__ */ jsx4(SheetTitle, { children: "Sidebar" }),
411
+ /* @__PURE__ */ jsx4(SheetDescription, { children: "Displays the mobile sidebar." })
412
+ ] }),
413
+ /* @__PURE__ */ jsx4("div", { className: "flex h-full w-full flex-col", children })
414
+ ]
415
+ }
416
+ ) });
417
+ }
418
+ return /* @__PURE__ */ jsxs3(
419
+ "div",
420
+ {
421
+ className: "group peer hidden text-sidebar-foreground md:block",
422
+ "data-state": state,
423
+ "data-collapsible": state === "collapsed" ? collapsible : "",
424
+ "data-variant": variant,
425
+ "data-side": side,
426
+ "data-slot": "sidebar",
427
+ children: [
428
+ /* @__PURE__ */ jsx4(
429
+ "div",
430
+ {
431
+ "data-slot": "sidebar-gap",
432
+ className: cn(
433
+ "relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear",
434
+ "group-data-[collapsible=offcanvas]:w-0",
435
+ "group-data-[side=right]:rotate-180",
436
+ variant === "floating" || variant === "inset" ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
437
+ )
438
+ }
439
+ ),
440
+ /* @__PURE__ */ jsx4(
441
+ "div",
442
+ {
443
+ "data-slot": "sidebar-container",
444
+ "data-side": side,
445
+ className: cn(
446
+ "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",
447
+ // Adjust the padding for floating and inset variants.
448
+ 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",
449
+ className
450
+ ),
451
+ ...props,
452
+ children: /* @__PURE__ */ jsx4(
453
+ "div",
454
+ {
455
+ "data-sidebar": "sidebar",
456
+ "data-slot": "sidebar-inner",
457
+ className: "flex size-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 group-data-[variant=floating]:ring-sidebar-border",
458
+ children
459
+ }
460
+ )
461
+ }
462
+ )
463
+ ]
464
+ }
465
+ );
466
+ }
467
+ function SidebarInset({ className, ...props }) {
468
+ return /* @__PURE__ */ jsx4(
469
+ "main",
470
+ {
471
+ "data-slot": "sidebar-inset",
472
+ className: cn(
473
+ "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",
474
+ className
475
+ ),
476
+ ...props
477
+ }
478
+ );
479
+ }
480
+ function SidebarHeader({ className, ...props }) {
481
+ return /* @__PURE__ */ jsx4(
482
+ "div",
483
+ {
484
+ "data-slot": "sidebar-header",
485
+ "data-sidebar": "header",
486
+ className: cn("flex flex-col gap-2 p-2", className),
487
+ ...props
488
+ }
489
+ );
490
+ }
491
+ function SidebarFooter({ className, ...props }) {
492
+ return /* @__PURE__ */ jsx4(
493
+ "div",
494
+ {
495
+ "data-slot": "sidebar-footer",
496
+ "data-sidebar": "footer",
497
+ className: cn("flex flex-col gap-2 p-2", className),
498
+ ...props
499
+ }
500
+ );
501
+ }
502
+ function SidebarContent({ className, ...props }) {
503
+ return /* @__PURE__ */ jsx4(
504
+ "div",
505
+ {
506
+ "data-slot": "sidebar-content",
507
+ "data-sidebar": "content",
508
+ className: cn(
509
+ "no-scrollbar flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
510
+ className
511
+ ),
512
+ ...props
513
+ }
514
+ );
515
+ }
516
+ function SidebarGroup({ className, ...props }) {
517
+ return /* @__PURE__ */ jsx4(
518
+ "div",
519
+ {
520
+ "data-slot": "sidebar-group",
521
+ "data-sidebar": "group",
522
+ className: cn("relative flex w-full min-w-0 flex-col p-2", className),
523
+ ...props
524
+ }
525
+ );
526
+ }
527
+ function SidebarGroupLabel({
528
+ className,
529
+ asChild = false,
530
+ render,
531
+ ...props
532
+ }) {
533
+ return /* @__PURE__ */ jsx4(
534
+ RenderSlot,
535
+ {
536
+ defaultTagName: "div",
537
+ asChild,
538
+ render,
539
+ "data-slot": "sidebar-group-label",
540
+ "data-sidebar": "group-label",
541
+ className: cn(
542
+ "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",
543
+ className
544
+ ),
545
+ ...props
546
+ }
547
+ );
548
+ }
549
+ function SidebarGroupContent({ className, ...props }) {
550
+ return /* @__PURE__ */ jsx4(
551
+ "div",
552
+ {
553
+ "data-slot": "sidebar-group-content",
554
+ "data-sidebar": "group-content",
555
+ className: cn("w-full text-sm", className),
556
+ ...props
557
+ }
558
+ );
559
+ }
560
+ function SidebarMenu({ className, ...props }) {
561
+ return /* @__PURE__ */ jsx4(
562
+ "ul",
563
+ {
564
+ "data-slot": "sidebar-menu",
565
+ "data-sidebar": "menu",
566
+ className: cn("flex w-full min-w-0 flex-col gap-1", className),
567
+ ...props
568
+ }
569
+ );
570
+ }
571
+ function SidebarMenuItem({ className, ...props }) {
572
+ return /* @__PURE__ */ jsx4(
573
+ "li",
574
+ {
575
+ "data-slot": "sidebar-menu-item",
576
+ "data-sidebar": "menu-item",
577
+ className: cn("group/menu-item relative", className),
578
+ ...props
579
+ }
580
+ );
581
+ }
582
+ var sidebarMenuButtonVariants = cva2(
583
+ "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",
584
+ {
585
+ variants: {
586
+ variant: {
587
+ default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
588
+ outline: "bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]"
589
+ },
590
+ size: {
591
+ default: "h-8 text-sm",
592
+ sm: "h-7 text-xs",
593
+ lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!"
594
+ }
595
+ },
596
+ defaultVariants: {
597
+ variant: "default",
598
+ size: "default"
599
+ }
600
+ }
601
+ );
602
+ function SidebarMenuButton({
603
+ asChild = false,
604
+ isActive = false,
605
+ variant = "default",
606
+ size = "default",
607
+ tooltip,
608
+ className,
609
+ render,
610
+ ...props
611
+ }) {
612
+ const { isMobile, state } = useSidebar();
613
+ const button = /* @__PURE__ */ jsx4(
614
+ RenderSlot,
615
+ {
616
+ defaultTagName: "button",
617
+ asChild,
618
+ render,
619
+ "data-slot": "sidebar-menu-button",
620
+ "data-sidebar": "menu-button",
621
+ "data-size": size,
622
+ "data-active": isActive ? "" : void 0,
623
+ className: cn(sidebarMenuButtonVariants({ variant, size }), className),
624
+ ...props
625
+ }
626
+ );
627
+ if (!tooltip) {
628
+ return button;
629
+ }
630
+ if (typeof tooltip === "string") {
631
+ tooltip = {
632
+ children: tooltip
633
+ };
634
+ }
635
+ return /* @__PURE__ */ jsxs3(Tooltip, { children: [
636
+ /* @__PURE__ */ jsx4(TooltipTrigger, { asChild: true, children: button }),
637
+ /* @__PURE__ */ jsx4(
638
+ TooltipContent,
639
+ {
640
+ side: "right",
641
+ align: "center",
642
+ hidden: state !== "collapsed" || isMobile,
643
+ ...tooltip
644
+ }
645
+ )
646
+ ] });
647
+ }
648
+ function SidebarMenuBadge({ className, ...props }) {
649
+ return /* @__PURE__ */ jsx4(
650
+ "div",
651
+ {
652
+ "data-slot": "sidebar-menu-badge",
653
+ "data-sidebar": "menu-badge",
654
+ className: cn(
655
+ "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",
656
+ className
657
+ ),
658
+ ...props
659
+ }
660
+ );
661
+ }
662
+
663
+ // ../ui/src/warmio/sidebar.tsx
664
+ import { jsx as jsx5 } from "react/jsx-runtime";
665
+ function SidebarProvider2({
666
+ className: _className,
667
+ presentation,
668
+ style: _style,
669
+ ...props
670
+ }) {
671
+ const presentationClassName = presentation === "mockup" ? "min-h-0 [--sidebar-width:16rem]" : presentation === "preview" ? "min-h-full" : void 0;
672
+ return /* @__PURE__ */ jsx5(SidebarProvider, { ...props, className: presentationClassName });
673
+ }
674
+ function Sidebar2({
675
+ className: _className,
676
+ presentation,
677
+ style: _style,
678
+ ...props
679
+ }) {
680
+ return /* @__PURE__ */ jsx5(
681
+ Sidebar,
682
+ {
683
+ ...props,
684
+ className: presentation === "product" ? "border-r border-border" : void 0
685
+ }
686
+ );
687
+ }
688
+ function SidebarInset2({
689
+ className: _className,
690
+ presentation,
691
+ style: _style,
692
+ ...props
693
+ }) {
694
+ return /* @__PURE__ */ jsx5(SidebarInset, { ...props, className: presentation === "product" ? "min-w-0" : void 0 });
695
+ }
696
+ function SidebarHeader2({
697
+ className: _className,
698
+ presentation,
699
+ style: _style,
700
+ ...props
701
+ }) {
702
+ const className = presentation === "product" ? "h-[var(--header-height)] justify-center border-b border-border p-2" : presentation === "mockup" ? "h-14 justify-center border-b border-border p-2" : void 0;
703
+ return /* @__PURE__ */ jsx5(SidebarHeader, { ...props, className });
704
+ }
705
+ function SidebarContent2({
706
+ className: _className,
707
+ presentation,
708
+ style: _style,
709
+ ...props
710
+ }) {
711
+ const className = presentation === "product" ? "pb-0" : presentation === "mockup" ? "px-1 py-3" : void 0;
712
+ return /* @__PURE__ */ jsx5(SidebarContent, { ...props, className });
713
+ }
714
+ function SidebarFooter2({
715
+ className: _className,
716
+ presentation,
717
+ style: _style,
718
+ ...props
719
+ }) {
720
+ return /* @__PURE__ */ jsx5(
721
+ SidebarFooter,
722
+ {
723
+ ...props,
724
+ className: presentation === "product" ? "border-t border-border p-2" : void 0
725
+ }
726
+ );
727
+ }
728
+ function SidebarGroup2({
729
+ className: _className,
730
+ collapsed = false,
731
+ presentation,
732
+ style: _style,
733
+ ...props
734
+ }) {
735
+ const className = presentation === "navigation" ? `${collapsed ? "items-center " : ""}px-2 py-1` : presentation === "mockup" ? "py-1" : void 0;
736
+ return /* @__PURE__ */ jsx5(SidebarGroup, { ...props, className });
737
+ }
738
+ function SidebarGroupContent2({
739
+ className: _className,
740
+ style: _style,
741
+ ...props
742
+ }) {
743
+ return /* @__PURE__ */ jsx5(SidebarGroupContent, { ...props });
744
+ }
745
+ function SidebarGroupLabel2({
746
+ className: _className,
747
+ presentation,
748
+ style: _style,
749
+ ...props
750
+ }) {
751
+ const className = presentation === "navigation" ? "px-2 tabular-nums text-xs uppercase tracking-wider text-sidebar-foreground/60" : presentation === "mockup" ? "uppercase tracking-wider" : void 0;
752
+ return /* @__PURE__ */ jsx5(SidebarGroupLabel, { ...props, className });
753
+ }
754
+ function SidebarMenu2({ className: _className, style: _style, ...props }) {
755
+ return /* @__PURE__ */ jsx5(SidebarMenu, { ...props });
756
+ }
757
+ function SidebarMenuItem2({
758
+ className: _className,
759
+ style: _style,
760
+ ...props
761
+ }) {
762
+ return /* @__PURE__ */ jsx5(SidebarMenuItem, { ...props });
763
+ }
764
+ function SidebarMenuButton2({
765
+ className: _className,
766
+ presentation,
767
+ style: _style,
768
+ ...props
769
+ }) {
770
+ const className = presentation === "account" ? "h-12" : presentation === "disabled" ? "text-muted-foreground/60" : presentation === "previewCollapsed" ? "mx-auto size-8 gap-0 p-2" : void 0;
771
+ return /* @__PURE__ */ jsx5(SidebarMenuButton, { ...props, className });
772
+ }
773
+ function SidebarMenuBadge2({
774
+ className: _className,
775
+ presentation,
776
+ style: _style,
777
+ ...props
778
+ }) {
779
+ return /* @__PURE__ */ jsx5(
780
+ SidebarMenuBadge,
781
+ {
782
+ ...props,
783
+ className: presentation === "attention" ? "animate-pulse" : void 0
784
+ }
785
+ );
786
+ }
787
+
788
+ export {
789
+ useSidebar,
790
+ SidebarProvider2 as SidebarProvider,
791
+ Sidebar2 as Sidebar,
792
+ SidebarInset2 as SidebarInset,
793
+ SidebarHeader2 as SidebarHeader,
794
+ SidebarContent2 as SidebarContent,
795
+ SidebarFooter2 as SidebarFooter,
796
+ SidebarGroup2 as SidebarGroup,
797
+ SidebarGroupContent2 as SidebarGroupContent,
798
+ SidebarGroupLabel2 as SidebarGroupLabel,
799
+ SidebarMenu2 as SidebarMenu,
800
+ SidebarMenuItem2 as SidebarMenuItem,
801
+ SidebarMenuButton2 as SidebarMenuButton,
802
+ SidebarMenuBadge2 as SidebarMenuBadge
803
+ };
@@ -0,0 +1,91 @@
1
+ import {
2
+ cn
3
+ } from "./chunk-VIB7OX7D.js";
4
+
5
+ // ../ui/src/components/logo.tsx
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ var WarmLogoIcon = ({
8
+ className = "h-5 w-5",
9
+ width = 20,
10
+ height = 16,
11
+ ...props
12
+ }) => {
13
+ return /* @__PURE__ */ jsxs(
14
+ "svg",
15
+ {
16
+ xmlns: "http://www.w3.org/2000/svg",
17
+ width,
18
+ height,
19
+ viewBox: "0 0 600 469",
20
+ className,
21
+ "aria-label": "Warm logo",
22
+ ...props,
23
+ children: [
24
+ /* @__PURE__ */ jsx(
25
+ "path",
26
+ {
27
+ d: "M 33.500 40.660 C 20.206 42.744, 0 48.560, -0 50.302 C -0 51.759, 123.955 348.889, 127.738 356.500 C 142.182 385.561, 169.450 410.275, 198.946 421.040 C 218.922 428.330, 243.683 430.825, 264.526 427.648 C 277.151 425.724, 294.628 420.011, 294.194 417.952 C 293.790 416.040, 172.732 124.599, 168.522 115.405 C 161.779 100.679, 149.168 84.171, 135.093 71.646 C 119.358 57.644, 98.880 47.362, 77 42.478 C 69.645 40.836, 40.220 39.606, 33.500 40.660",
28
+ fill: "var(--logo-primary)"
29
+ }
30
+ ),
31
+ /* @__PURE__ */ jsx(
32
+ "path",
33
+ {
34
+ d: "M 229.651 41.597 C 217.916 43.718, 202.443 49.144, 202.744 51.035 C 203.418 55.268, 329.689 356.584, 333.687 363.500 C 340.525 375.327, 345.293 381.483, 355.408 391.538 C 374.603 410.619, 398.878 423.014, 425.907 427.533 C 439.649 429.831, 463.594 429.132, 476 426.072 C 489.892 422.645, 497.188 419.815, 496.703 418.043 C 495.416 413.331, 371.058 116.094, 367.406 109 C 349.467 74.149, 313.008 47.875, 273.752 41.509 C 262.281 39.648, 240.195 39.693, 229.651 41.597",
35
+ fill: "var(--logo-primary)"
36
+ }
37
+ ),
38
+ /* @__PURE__ */ jsx(
39
+ "path",
40
+ {
41
+ d: "M 463 40.593 C 451.670 42.545, 447.288 43.569, 439 46.203 C 433.775 47.864, 429.338 49.372, 429.140 49.555 C 428.942 49.737, 434.670 64.021, 441.868 81.297 C 455.574 114.190, 462.215 131.660, 468.447 151.208 C 475.360 172.892, 486.124 186.213, 503.834 194.997 C 530.956 208.450, 564.982 201.679, 583.654 179.112 C 604.399 154.041, 605.407 121.944, 586.291 95.155 C 567.827 69.280, 539.107 50.114, 508 42.907 C 500.680 41.212, 494.713 40.644, 482 40.434 C 472.925 40.284, 464.375 40.356, 463 40.593",
42
+ fill: "var(--logo-accent)"
43
+ }
44
+ )
45
+ ]
46
+ }
47
+ );
48
+ };
49
+
50
+ // ../ui/src/warmio/logo.tsx
51
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
52
+ var iconSizeClasses = {
53
+ badge: "size-3",
54
+ default: "size-7",
55
+ feature: "size-8",
56
+ hero: "size-14"
57
+ };
58
+ var toneClasses = {
59
+ default: "",
60
+ foreground: "text-foreground",
61
+ sidebar: "text-sidebar-foreground"
62
+ };
63
+ function WarmLogoIcon2({
64
+ size = "default",
65
+ tone = "default",
66
+ decorative = false
67
+ }) {
68
+ return /* @__PURE__ */ jsx2(
69
+ WarmLogoIcon,
70
+ {
71
+ className: cn(iconSizeClasses[size], toneClasses[tone]),
72
+ "aria-hidden": decorative ? true : void 0,
73
+ "aria-label": decorative ? void 0 : "Warm logo"
74
+ }
75
+ );
76
+ }
77
+ var Logo = ({
78
+ size = "default",
79
+ tone = "default",
80
+ showText = true
81
+ }) => {
82
+ return /* @__PURE__ */ jsxs2("div", { className: "inline-flex items-center gap-2", children: [
83
+ /* @__PURE__ */ jsx2(WarmLogoIcon2, { size, tone, decorative: showText }),
84
+ showText ? /* @__PURE__ */ jsx2("span", { className: "text-sm font-bold tracking-wide text-foreground", children: "Warm" }) : null
85
+ ] });
86
+ };
87
+
88
+ export {
89
+ WarmLogoIcon2 as WarmLogoIcon,
90
+ Logo
91
+ };
@@ -0,0 +1,74 @@
1
+ import {
2
+ cn
3
+ } from "./chunk-VIB7OX7D.js";
4
+
5
+ // ../ui/src/warmio/badge.tsx
6
+ import { jsx } from "react/jsx-runtime";
7
+ var badgeToneClassNameByTone = {
8
+ default: "border-border bg-muted text-foreground",
9
+ info: "border-info/20 bg-info/10 text-info",
10
+ success: "border-success-border bg-success/10 text-success",
11
+ warning: "border-warning-border bg-warning/10 text-warning",
12
+ destructive: "border-destructive/20 bg-destructive/10 text-destructive"
13
+ };
14
+ var solidBadgeToneClassNameByTone = {
15
+ default: "border-foreground bg-foreground text-background",
16
+ info: "border-info bg-info text-background",
17
+ success: "border-success bg-success text-background",
18
+ warning: "border-warning bg-warning text-background",
19
+ destructive: "border-destructive bg-destructive text-destructive-foreground"
20
+ };
21
+ var badgeSizeClassNameBySize = {
22
+ sm: "h-5 px-2 py-2 text-xs",
23
+ default: "h-6 px-2 py-2 text-xs"
24
+ };
25
+ var badgeCircleClassNameBySize = {
26
+ sm: "size-5 px-0 py-0 text-xs leading-none",
27
+ default: "size-6 px-0 py-0 text-xs leading-none"
28
+ };
29
+ function Badge({
30
+ tone,
31
+ size = "default",
32
+ shape = "pill",
33
+ surface = "default",
34
+ placement = "inline",
35
+ emphasis = "subtle",
36
+ width = "auto",
37
+ truncate = false,
38
+ numeric = false,
39
+ children,
40
+ id,
41
+ "aria-label": ariaLabel
42
+ }) {
43
+ const resolvedTone = tone ?? "default";
44
+ return /* @__PURE__ */ jsx(
45
+ "span",
46
+ {
47
+ "data-slot": "badge",
48
+ "data-tone": resolvedTone,
49
+ "data-shape": shape,
50
+ "data-surface": surface,
51
+ "data-placement": placement,
52
+ id,
53
+ "aria-label": ariaLabel,
54
+ className: cn(
55
+ "inline-flex w-fit max-w-full items-center justify-center gap-2 overflow-hidden rounded-full border font-bold whitespace-nowrap transition-colors",
56
+ emphasis === "solid" ? solidBadgeToneClassNameByTone[resolvedTone] : badgeToneClassNameByTone[resolvedTone],
57
+ badgeSizeClassNameBySize[size],
58
+ shape === "circle" && badgeCircleClassNameBySize[size],
59
+ surface === "floating" && "border-background ring-2 ring-background",
60
+ placement === "top-end" && "pointer-events-none absolute -right-2 -top-2 z-10",
61
+ width === "metric" && "w-12",
62
+ width === "compact" && "min-w-6",
63
+ truncate ? "min-w-0 shrink truncate" : "shrink-0",
64
+ numeric && "tabular-nums",
65
+ "[&>svg]:shrink-0 [&>svg:not([class*=size-])]:size-3"
66
+ ),
67
+ children: truncate ? /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children }) : children
68
+ }
69
+ );
70
+ }
71
+
72
+ export {
73
+ Badge
74
+ };
@@ -0,0 +1,10 @@
1
+ // ../ui/src/lib/utils.ts
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ function cn(...inputs) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+
8
+ export {
9
+ cn
10
+ };
package/dist/index.js ADDED
@@ -0,0 +1,43 @@
1
+ import {
2
+ Badge
3
+ } from "./chunks/chunk-ICC7GQXS.js";
4
+ import {
5
+ Logo,
6
+ WarmLogoIcon
7
+ } from "./chunks/chunk-HMXXCKZG.js";
8
+ import {
9
+ Sidebar,
10
+ SidebarContent,
11
+ SidebarFooter,
12
+ SidebarGroup,
13
+ SidebarGroupContent,
14
+ SidebarGroupLabel,
15
+ SidebarHeader,
16
+ SidebarInset,
17
+ SidebarMenu,
18
+ SidebarMenuBadge,
19
+ SidebarMenuButton,
20
+ SidebarMenuItem,
21
+ SidebarProvider,
22
+ useSidebar
23
+ } from "./chunks/chunk-EJ2CNGRW.js";
24
+ import "./chunks/chunk-VIB7OX7D.js";
25
+ export {
26
+ Badge,
27
+ Logo,
28
+ Sidebar,
29
+ SidebarContent,
30
+ SidebarFooter,
31
+ SidebarGroup,
32
+ SidebarGroupContent,
33
+ SidebarGroupLabel,
34
+ SidebarHeader,
35
+ SidebarInset,
36
+ SidebarMenu,
37
+ SidebarMenuBadge,
38
+ SidebarMenuButton,
39
+ SidebarMenuItem,
40
+ SidebarProvider,
41
+ WarmLogoIcon,
42
+ useSidebar
43
+ };
package/dist/logo.js ADDED
@@ -0,0 +1,9 @@
1
+ import {
2
+ Logo,
3
+ WarmLogoIcon
4
+ } from "./chunks/chunk-HMXXCKZG.js";
5
+ import "./chunks/chunk-VIB7OX7D.js";
6
+ export {
7
+ Logo,
8
+ WarmLogoIcon
9
+ };
@@ -0,0 +1,33 @@
1
+ import {
2
+ Sidebar,
3
+ SidebarContent,
4
+ SidebarFooter,
5
+ SidebarGroup,
6
+ SidebarGroupContent,
7
+ SidebarGroupLabel,
8
+ SidebarHeader,
9
+ SidebarInset,
10
+ SidebarMenu,
11
+ SidebarMenuBadge,
12
+ SidebarMenuButton,
13
+ SidebarMenuItem,
14
+ SidebarProvider,
15
+ useSidebar
16
+ } from "./chunks/chunk-EJ2CNGRW.js";
17
+ import "./chunks/chunk-VIB7OX7D.js";
18
+ export {
19
+ Sidebar,
20
+ SidebarContent,
21
+ SidebarFooter,
22
+ SidebarGroup,
23
+ SidebarGroupContent,
24
+ SidebarGroupLabel,
25
+ SidebarHeader,
26
+ SidebarInset,
27
+ SidebarMenu,
28
+ SidebarMenuBadge,
29
+ SidebarMenuButton,
30
+ SidebarMenuItem,
31
+ SidebarProvider,
32
+ useSidebar
33
+ };
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@warmio/ui",
3
+ "version": "1.0.0",
4
+ "description": "Portable React components for Warm products.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/jasonstockman/warm-app.git",
11
+ "directory": "libraries/public-ui"
12
+ },
13
+ "homepage": "https://github.com/jasonstockman/warm-app/tree/master/libraries/public-ui",
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "types",
20
+ "README.md"
21
+ ],
22
+ "exports": {
23
+ ".": {
24
+ "types": "./types/index.d.ts",
25
+ "import": "./dist/index.js",
26
+ "default": "./dist/index.js"
27
+ },
28
+ "./badge": {
29
+ "types": "./types/badge.d.ts",
30
+ "import": "./dist/badge.js",
31
+ "default": "./dist/badge.js"
32
+ },
33
+ "./logo": {
34
+ "types": "./types/logo.d.ts",
35
+ "import": "./dist/logo.js",
36
+ "default": "./dist/logo.js"
37
+ },
38
+ "./sidebar": {
39
+ "types": "./types/sidebar.d.ts",
40
+ "import": "./dist/sidebar.js",
41
+ "default": "./dist/sidebar.js"
42
+ }
43
+ },
44
+ "peerDependencies": {
45
+ "@base-ui/react": ">=1.6.0 <2.0.0",
46
+ "@warmio/design": "1.0.0",
47
+ "class-variance-authority": "^0.7.1",
48
+ "clsx": "^2.1.1",
49
+ "lucide-react": ">=0.562.0 <2.0.0",
50
+ "react": ">=19.0.0",
51
+ "react-dom": ">=19.0.0",
52
+ "tailwind-merge": ">=3.6.0 <4.0.0"
53
+ },
54
+ "devDependencies": {
55
+ "esbuild": "^0.28.1"
56
+ },
57
+ "scripts": {
58
+ "build": "node scripts/build.mjs",
59
+ "pack:check": "node ../../tools/tasks/check-ui-package.mjs",
60
+ "prepack": "pnpm build"
61
+ }
62
+ }
@@ -0,0 +1,21 @@
1
+ import type { AriaAttributes, ReactNode } from 'react';
2
+
3
+ export type FeedbackTone = 'default' | 'info' | 'success' | 'warning' | 'destructive';
4
+ export type FeedbackSize = 'sm' | 'default';
5
+
6
+ export type BadgeProps = {
7
+ tone?: FeedbackTone;
8
+ size?: FeedbackSize;
9
+ shape?: 'pill' | 'circle';
10
+ surface?: 'default' | 'floating';
11
+ placement?: 'inline' | 'top-end';
12
+ emphasis?: 'subtle' | 'solid';
13
+ width?: 'auto' | 'metric' | 'compact';
14
+ truncate?: boolean;
15
+ children?: ReactNode;
16
+ numeric?: boolean;
17
+ id?: string;
18
+ 'aria-label'?: AriaAttributes['aria-label'];
19
+ };
20
+
21
+ export declare function Badge(props: BadgeProps): ReactNode;
@@ -0,0 +1,3 @@
1
+ export * from './badge.js';
2
+ export * from './logo.js';
3
+ export * from './sidebar.js';
@@ -0,0 +1,25 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export type WarmLogoSize = 'badge' | 'default' | 'feature' | 'hero';
4
+ export type WarmLogoTone = 'default' | 'foreground' | 'sidebar';
5
+
6
+ type StrictLogoProps = {
7
+ className?: never;
8
+ style?: never;
9
+ textClass?: never;
10
+ };
11
+
12
+ export type WarmLogoIconProps = StrictLogoProps & {
13
+ size?: WarmLogoSize;
14
+ tone?: WarmLogoTone;
15
+ decorative?: boolean;
16
+ };
17
+
18
+ export type LogoProps = StrictLogoProps & {
19
+ size?: WarmLogoSize;
20
+ tone?: WarmLogoTone;
21
+ showText?: boolean;
22
+ };
23
+
24
+ export declare function WarmLogoIcon(props: WarmLogoIconProps): ReactNode;
25
+ export declare function Logo(props: LogoProps): ReactNode;
@@ -0,0 +1,93 @@
1
+ import type { ComponentProps, ReactElement, ReactNode } from 'react';
2
+
3
+ type WithoutChrome<T> = Omit<T, 'className' | 'style'> & {
4
+ className?: never;
5
+ style?: never;
6
+ };
7
+
8
+ export type SidebarProviderProps = WithoutChrome<ComponentProps<'div'>> & {
9
+ defaultOpen?: boolean;
10
+ open?: boolean;
11
+ onOpenChange?: (open: boolean) => void;
12
+ forceIconAtTablet?: boolean;
13
+ allowUserCollapse?: boolean;
14
+ presentation?: 'mockup' | 'preview';
15
+ };
16
+
17
+ export type SidebarProps = WithoutChrome<ComponentProps<'div'>> & {
18
+ side?: 'left' | 'right';
19
+ variant?: 'sidebar' | 'floating' | 'inset';
20
+ collapsible?: 'offcanvas' | 'icon' | 'none';
21
+ presentation?: 'product';
22
+ };
23
+
24
+ export type SidebarInsetProps = WithoutChrome<ComponentProps<'main'>> & {
25
+ presentation?: 'product';
26
+ };
27
+
28
+ export type SidebarHeaderProps = WithoutChrome<ComponentProps<'div'>> & {
29
+ presentation?: 'mockup' | 'product';
30
+ };
31
+
32
+ export type SidebarContentProps = WithoutChrome<ComponentProps<'div'>> & {
33
+ presentation?: 'mockup' | 'product';
34
+ };
35
+
36
+ export type SidebarFooterProps = WithoutChrome<ComponentProps<'div'>> & {
37
+ presentation?: 'product';
38
+ };
39
+
40
+ export type SidebarGroupProps = WithoutChrome<ComponentProps<'div'>> & {
41
+ collapsed?: boolean;
42
+ presentation?: 'mockup' | 'navigation';
43
+ };
44
+
45
+ export type SidebarGroupContentProps = WithoutChrome<ComponentProps<'div'>>;
46
+
47
+ export type SidebarGroupLabelProps = WithoutChrome<ComponentProps<'div'>> & {
48
+ asChild?: boolean;
49
+ render?: ReactElement;
50
+ presentation?: 'mockup' | 'navigation';
51
+ };
52
+
53
+ export type SidebarMenuProps = WithoutChrome<ComponentProps<'ul'>>;
54
+ export type SidebarMenuItemProps = WithoutChrome<ComponentProps<'li'>>;
55
+
56
+ export type SidebarMenuButtonProps = WithoutChrome<ComponentProps<'button'>> & {
57
+ asChild?: boolean;
58
+ isActive?: boolean;
59
+ tooltip?: string | ReactNode;
60
+ render?: ReactElement;
61
+ variant?: 'default' | 'outline' | null;
62
+ size?: 'default' | 'sm' | 'lg' | null;
63
+ presentation?: 'account' | 'disabled' | 'previewCollapsed';
64
+ };
65
+
66
+ export type SidebarMenuBadgeProps = WithoutChrome<ComponentProps<'div'>> & {
67
+ presentation?: 'attention';
68
+ };
69
+
70
+ export type SidebarContextValue = {
71
+ state: 'expanded' | 'collapsed';
72
+ open: boolean;
73
+ setOpen: (open: boolean | ((open: boolean) => boolean)) => void;
74
+ openMobile: boolean;
75
+ setOpenMobile: (open: boolean | ((open: boolean) => boolean)) => void;
76
+ isMobile: boolean;
77
+ toggleSidebar: () => void;
78
+ };
79
+
80
+ export declare function SidebarProvider(props: SidebarProviderProps): ReactNode;
81
+ export declare function Sidebar(props: SidebarProps): ReactNode;
82
+ export declare function SidebarInset(props: SidebarInsetProps): ReactNode;
83
+ export declare function SidebarHeader(props: SidebarHeaderProps): ReactNode;
84
+ export declare function SidebarContent(props: SidebarContentProps): ReactNode;
85
+ export declare function SidebarFooter(props: SidebarFooterProps): ReactNode;
86
+ export declare function SidebarGroup(props: SidebarGroupProps): ReactNode;
87
+ export declare function SidebarGroupContent(props: SidebarGroupContentProps): ReactNode;
88
+ export declare function SidebarGroupLabel(props: SidebarGroupLabelProps): ReactNode;
89
+ export declare function SidebarMenu(props: SidebarMenuProps): ReactNode;
90
+ export declare function SidebarMenuItem(props: SidebarMenuItemProps): ReactNode;
91
+ export declare function SidebarMenuButton(props: SidebarMenuButtonProps): ReactNode;
92
+ export declare function SidebarMenuBadge(props: SidebarMenuBadgeProps): ReactNode;
93
+ export declare function useSidebar(): SidebarContextValue;