@cloudgrid-io/ui 0.27.2 → 0.28.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.
@@ -0,0 +1,265 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
5
+ import { cva } from "class-variance-authority";
6
+ import { cn } from "../lib/cloudgrid-cn.js";
7
+ import { Button } from "./button.js";
8
+ import { CloseIcon } from "../blocks/icons.js";
9
+ /**
10
+ * The sheet that slides in from an edge (#214).
11
+ *
12
+ * `Dialog` is centred. Nothing in this library came in from the side, so the
13
+ * console hand-composes the same panel eight times: five shipped surfaces on its
14
+ * local `Overlay` primitive (`UserDetailsDrawer`, `FeedbackDetailDrawer`,
15
+ * `VaultGrantsDrawer`, `ConnectorAuditDrawer`, `PerEntityCapDrawer`) and three
16
+ * more drawn in the app page facelift (the Secrets update panel, the Database
17
+ * record details panel, the Domains setup wizard). Each copy guesses its own
18
+ * width, lays out its own title row and picks its own close-button size.
19
+ *
20
+ * `Overlay.taxonomy.md` in the console has carried the line "a future Drawer
21
+ * slides from the right" since that primitive was written. This is it.
22
+ *
23
+ * ## Why this is a positioned Dialog and not Base UI's own Drawer
24
+ *
25
+ * Base UI 1.7.0 ships `Drawer`, and its usage guidelines answer the question
26
+ * directly: "Drawer extends Dialog: it adds gesture support, snap points, and
27
+ * indent effects. If you don't need these, use Dialog instead. A panel that
28
+ * slides in from the edge of the screen and doesn't need gesture support is a
29
+ * positioned Dialog."
30
+ *
31
+ * None of the eight consumers swipes. They are desktop side panels opened from a
32
+ * table row or a button, and the one phone surface (`PlugSheet`) dismisses with
33
+ * its close glyph and the scrim. `Drawer` would also bring `Drawer.Viewport` and
34
+ * a swipe layer this repo has no way to test in Playwright, in exchange for
35
+ * behaviour nobody asked for. If a consumer ever needs swipe-to-dismiss, that is
36
+ * Base UI's `Drawer` and its own issue, not a prop here.
37
+ *
38
+ * ## The size rungs, and where they come from
39
+ *
40
+ * `size` is a named rung rather than a Tailwind class handed in by the caller,
41
+ * which is the whole point of #214: five files currently decide independently how
42
+ * wide a drawer is.
43
+ *
44
+ * md 448px max-w-md
45
+ * lg 512px max-w-lg
46
+ *
47
+ * Both were measured off the founder's frames rather than chosen. The three app
48
+ * page frames export at 1024px against a 1600px design, so the scale is 1.5625:
49
+ *
50
+ * Secrets, "Update secret" 287px exported 448px -> md
51
+ * Database, "Record details" 287px exported 448px -> md
52
+ * Domains, "Set up chimp.me" 325px exported 508px -> lg
53
+ *
54
+ * They land on the two rungs the console already writes by hand: `max-w-md` on
55
+ * three of the five shipped drawers, `max-w-lg` on the newest. #694's own frame
56
+ * is 525 of 1600, which is `lg` to the nearest rung.
57
+ *
58
+ * There is deliberately no third rung. Two values cover every frame and every
59
+ * shipped copy, and a wider one with nothing behind it would be a worker
60
+ * inventing a brand decision.
61
+ *
62
+ * `size` is the INLINE width and applies to `left` and `right` only. A bottom
63
+ * sheet is full width, which is what `PlugSheet` already does.
64
+ *
65
+ * ## Full width at the narrow end, without opting in
66
+ *
67
+ * The popup is `w-full` under a `max-w-*` rung, so below 448px it simply fills
68
+ * the screen. No breakpoint prop, no phone variant, nothing for a caller to
69
+ * remember. #214 asks for exactly this.
70
+ *
71
+ * ## Ground: opaque on every surface
72
+ *
73
+ * The trap `Popover` fell into and #230 records. `bg-popover` resolves to
74
+ * `--cg-surface-card`, which is `transparent` inside `[data-cg-surface='panel']`
75
+ * and a 4% white wash inside `[data-cg-surface='ink']`, because a CARD on a dark
76
+ * brand surface is meant to let it through. An overlay is the one thing that
77
+ * cannot: it is drawn over arbitrary content, and a see-through drawer renders
78
+ * its words and the page's in the same pixels.
79
+ *
80
+ * So the ground is opaque in all three scopes, out of values this system already
81
+ * has: the card ground on the page, `--cg-surface-panel` on the panel,
82
+ * `--cg-surface-code` on ink. No new token and no new colour. Guarded by an alpha
83
+ * assertion on all three grounds in `registry/e2e/drawer.spec.ts`, the same check
84
+ * `popover.test.mjs` and that spec added for #228.
85
+ *
86
+ * ## `container`, and the surface a portal leaves behind
87
+ *
88
+ * Base UI portals to `<body>`, which is outside every `data-cg-surface` scope, and
89
+ * every `--cg-*` value here is inherited. A drawer opened from inside an ink
90
+ * header would render with the page's tokens and look entirely correct.
91
+ * `container` forwards to `Dialog.Portal`'s own prop, exactly as `PopoverContent`
92
+ * does, so a consumer can keep the portal inside the surface it belongs to.
93
+ *
94
+ * It changes the token scope, not the geometry: the popup is `fixed`, so it is
95
+ * anchored to the viewport edge wherever the portal lives. That is what all five
96
+ * console drawers do today. The frames draw the drawer inside the page box
97
+ * because on that page the box fills the window.
98
+ *
99
+ * It was worth checking that a mid-page portal does not cost a MODAL its focus
100
+ * trap, since Base UI's focus guards are siblings of the portal node rather than
101
+ * of `<body>` and a popover is not modal, so #228 never had to care. It does not:
102
+ * eighteen Tab and Shift+Tab presses inside a contained drawer never reach a
103
+ * control outside it, asserted in `registry/e2e/drawer.spec.ts`. An earlier
104
+ * throwaway probe appeared to show a leak and was wrong: it tabbed within a few
105
+ * milliseconds of the popup appearing, before Base UI had armed the trap, which
106
+ * is a race in the probe rather than a property of the component.
107
+ *
108
+ * ## Stacking, which is the bug that forced this issue
109
+ *
110
+ * console#694: the drawer's Remove opens the existing confirm modal, both listen
111
+ * for Escape on the document, and one keystroke dismissed the confirm AND the
112
+ * drawer behind it. The console guards it by making the drawer's `onClose` inert
113
+ * while the confirm is open, which every caller has to remember.
114
+ *
115
+ * Base UI makes the topmost dialog the only one that hears Escape, as long as the
116
+ * nested `Drawer`/`Dialog` root is rendered INSIDE the parent's popup. Nothing
117
+ * here implements that, so the spec proves it rather than the docblock claiming
118
+ * it.
119
+ *
120
+ * What this library DOES have to implement is the layering. Base UI suppresses a
121
+ * nested dialog's backdrop by default, so the first version of this left the
122
+ * drawer at full brightness under an open confirm: two bright surfaces, reading as
123
+ * one broken one rather than as a dialog on top of a sheet. Both overlays here and
124
+ * in `dialog.tsx` therefore pass `forceRender`, so whatever is on top brings its
125
+ * own scrim and everything under it dims, the drawer included.
126
+ *
127
+ * Stacking order needs no z-index of its own. A nested dialog always OPENS after
128
+ * its parent, so its portal is appended later and paints above at the same `z-50`.
129
+ */
130
+ /**
131
+ * The positioning container, and the edge the sheet is pinned to.
132
+ *
133
+ * `fixed inset-0` with one flex alignment per side, which is precisely the shape
134
+ * the console writes as `scrimClassName="flex justify-end"` five times over. It
135
+ * is Base UI's `Dialog.Viewport`, so it carries the open and nested data
136
+ * attributes and Base UI treats a press on it as an outside press.
137
+ */
138
+ const drawerViewportVariants = cva("fixed inset-0 z-50 flex", {
139
+ variants: {
140
+ side: {
141
+ right: "justify-end",
142
+ left: "justify-start",
143
+ bottom: "flex-col justify-end",
144
+ },
145
+ },
146
+ defaultVariants: {
147
+ side: "right",
148
+ },
149
+ });
150
+ /**
151
+ * The sheet itself.
152
+ *
153
+ * `flex flex-col` with `overflow-hidden` is what lets `DrawerBody` scroll while
154
+ * the header and footer hold their place: the body is the only child that grows,
155
+ * and the popup never scrolls as a whole.
156
+ */
157
+ const drawerPopupVariants = cva([
158
+ "relative isolate z-50 flex w-full flex-col overflow-hidden text-body-sm text-popover-foreground shadow-raised outline-none",
159
+ // The ground, opaque per scope. See the docblock: `bg-popover` alone is #230.
160
+ "bg-popover in-data-[cg-surface=panel]:bg-panel in-data-[cg-surface=ink]:bg-code",
161
+ "duration-150 data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
162
+ ], {
163
+ variants: {
164
+ side: {
165
+ right: "h-full border-l border-line data-open:slide-in-from-right data-closed:slide-out-to-right",
166
+ left: "h-full border-r border-line data-open:slide-in-from-left data-closed:slide-out-to-left",
167
+ // 85svh, not 85vh: on a phone `vh` is measured against the largest
168
+ // viewport, so the sheet sits partly under the browser chrome while the
169
+ // URL bar is showing. `PlugSheet` has the same 85% and the older unit.
170
+ bottom: "max-h-[85svh] rounded-t-xl border-t border-line data-open:slide-in-from-bottom data-closed:slide-out-to-bottom",
171
+ },
172
+ size: {
173
+ md: "max-w-md",
174
+ lg: "max-w-lg",
175
+ },
176
+ },
177
+ compoundVariants: [
178
+ // A bottom sheet is full width. The rungs are the inline axis, and on this
179
+ // edge the inline axis is the whole screen.
180
+ { side: "bottom", size: "md", class: "max-w-none" },
181
+ { side: "bottom", size: "lg", class: "max-w-none" },
182
+ ],
183
+ defaultVariants: {
184
+ side: "right",
185
+ size: "md",
186
+ },
187
+ });
188
+ function Drawer({ ...props }) {
189
+ return _jsx(DialogPrimitive.Root, { "data-slot": "drawer", ...props });
190
+ }
191
+ function DrawerTrigger({ ...props }) {
192
+ return _jsx(DialogPrimitive.Trigger, { "data-slot": "drawer-trigger", ...props });
193
+ }
194
+ function DrawerPortal({ ...props }) {
195
+ return _jsx(DialogPrimitive.Portal, { "data-slot": "drawer-portal", ...props });
196
+ }
197
+ function DrawerClose({ ...props }) {
198
+ return _jsx(DialogPrimitive.Close, { "data-slot": "drawer-close", ...props });
199
+ }
200
+ /**
201
+ * The scrim.
202
+ *
203
+ * `bg-scrim` is `--cg-scrim`, the token the console's `Overlay` already reads
204
+ * inline and the one this system declares for exactly this job. It is deliberately
205
+ * declared at `:root` only and does not flip: a scrim composites over whatever is
206
+ * behind it, so it has no surface of its own.
207
+ *
208
+ * `forceRender` because Base UI does not render a nested dialog's backdrop by
209
+ * default. See the stacking note in the component docblock.
210
+ */
211
+ function DrawerOverlay({ className, forceRender = true, ...props }) {
212
+ return (_jsx(DialogPrimitive.Backdrop, { "data-slot": "drawer-overlay", forceRender: forceRender, className: cn("fixed inset-0 isolate z-50 bg-scrim duration-150 data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0", className), ...props }));
213
+ }
214
+ function DrawerContent({ side = "right", size = "md", container, className, children, ...props }) {
215
+ return (_jsxs(DrawerPortal, { container: container, children: [_jsx(DrawerOverlay, {}), _jsx(DialogPrimitive.Viewport, { className: drawerViewportVariants({ side }), children: _jsx(DialogPrimitive.Popup, { "data-slot": "drawer-content", "data-side": side, "data-size": size, className: cn(drawerPopupVariants({ side, size }), className), ...props, children: children }) })] }));
216
+ }
217
+ /**
218
+ * The title row, with the close affordance built in.
219
+ *
220
+ * The part of #214 that is not geometry. All eight copies lay this row out
221
+ * themselves and the newest had to pick its own close-button size, so the header
222
+ * owns the arrangement: the title on the left, the close glyph top right at the
223
+ * library's own icon rung, an optional description under it, and `children` for
224
+ * the identity row the frames draw in that slot (the secret's key, the record's
225
+ * collection and status chip, the wizard's step strip).
226
+ *
227
+ * `aria-labelledby` needs no wiring: `DrawerTitle` is Base UI's `Dialog.Title`,
228
+ * which registers its own id on the popup. Passing `title` rather than leaving it
229
+ * to the caller is what guarantees every drawer has one.
230
+ */
231
+ function DrawerHeader({ title, description, closeLabel = "Close", showCloseButton = true, className, children, ...props }) {
232
+ return (_jsxs("div", { "data-slot": "drawer-header", className: cn("flex shrink-0 flex-col gap-2 px-6 pt-5 pb-4", className), ...props, children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsx(DrawerTitle, { children: title }), showCloseButton && (_jsxs(DialogPrimitive.Close, { "data-slot": "drawer-close", render: _jsx(Button, { variant: "ghost", size: "icon-sm", className: "-mt-1 -mr-1.5" }), children: [_jsx(CloseIcon, {}), _jsx("span", { className: "sr-only", children: closeLabel })] }))] }), description ? _jsx(DrawerDescription, { children: description }) : null, children] }));
233
+ }
234
+ /**
235
+ * The scrolling half.
236
+ *
237
+ * `min-h-0` is load-bearing and invisible: a flex child's default `min-height` is
238
+ * `auto`, so without it the body refuses to shrink below its content and the
239
+ * whole sheet grows past the viewport instead of scrolling inside itself. The
240
+ * footer then leaves the screen, which is the one thing a pinned footer must not
241
+ * do.
242
+ */
243
+ function DrawerBody({ className, ...props }) {
244
+ return (_jsx("div", { "data-slot": "drawer-body", className: cn("min-h-0 flex-1 overflow-y-auto px-6 pb-5", className), ...props }));
245
+ }
246
+ /**
247
+ * The pinned half.
248
+ *
249
+ * `shrink-0` keeps it out of the scroll. It carries a hairline where the header
250
+ * does not: the frames draw neither, but the header sits above content that
251
+ * starts at the top of the sheet while the footer sits above content that has
252
+ * been scrolled under it, and a pinned bar with nothing between it and moving
253
+ * text reads as part of the text.
254
+ */
255
+ function DrawerFooter({ className, ...props }) {
256
+ return (_jsx("div", { "data-slot": "drawer-footer", className: cn("flex shrink-0 flex-wrap items-center justify-end gap-2 border-t border-hairline px-6 py-4", className), ...props }));
257
+ }
258
+ function DrawerTitle({ className, ...props }) {
259
+ return (_jsx(DialogPrimitive.Title, { "data-slot": "drawer-title", className: cn("font-heading text-body-lg leading-none font-medium", className), ...props }));
260
+ }
261
+ function DrawerDescription({ className, ...props }) {
262
+ return (_jsx(DialogPrimitive.Description, { "data-slot": "drawer-description", className: cn("text-caption text-body", className), ...props }));
263
+ }
264
+ export { Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, drawerPopupVariants, drawerViewportVariants, };
265
+ //# sourceMappingURL=drawer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drawer.js","sourceRoot":"","sources":["../../src/ui/drawer.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACjE,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAA;AAEjE,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwHG;AAEH;;;;;;;GAOG;AACH,MAAM,sBAAsB,GAAG,GAAG,CAAC,yBAAyB,EAAE;IAC5D,QAAQ,EAAE;QACR,IAAI,EAAE;YACJ,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,sBAAsB;SAC/B;KACF;IACD,eAAe,EAAE;QACf,IAAI,EAAE,OAAO;KACd;CACF,CAAC,CAAA;AAEF;;;;;;GAMG;AACH,MAAM,mBAAmB,GAAG,GAAG,CAC7B;IACE,4HAA4H;IAC5H,8EAA8E;IAC9E,iFAAiF;IACjF,sGAAsG;CACvG,EACD;IACE,QAAQ,EAAE;QACR,IAAI,EAAE;YACJ,KAAK,EACH,0FAA0F;YAC5F,IAAI,EAAE,wFAAwF;YAC9F,mEAAmE;YACnE,wEAAwE;YACxE,uEAAuE;YACvE,MAAM,EACJ,gHAAgH;SACnH;QACD,IAAI,EAAE;YACJ,EAAE,EAAE,UAAU;YACd,EAAE,EAAE,UAAU;SACf;KACF;IACD,gBAAgB,EAAE;QAChB,2EAA2E;QAC3E,4CAA4C;QAC5C,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE;QACnD,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE;KACpD;IACD,eAAe,EAAE;QACf,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,IAAI;KACX;CACF,CACF,CAAA;AAED,SAAS,MAAM,CAAC,EAAE,GAAG,KAAK,EAA8B;IACtD,OAAO,KAAC,eAAe,CAAC,IAAI,iBAAW,QAAQ,KAAK,KAAK,GAAI,CAAA;AAC/D,CAAC;AAED,SAAS,aAAa,CAAC,EAAE,GAAG,KAAK,EAAiC;IAChE,OAAO,KAAC,eAAe,CAAC,OAAO,iBAAW,gBAAgB,KAAK,KAAK,GAAI,CAAA;AAC1E,CAAC;AAED,SAAS,YAAY,CAAC,EAAE,GAAG,KAAK,EAAgC;IAC9D,OAAO,KAAC,eAAe,CAAC,MAAM,iBAAW,eAAe,KAAK,KAAK,GAAI,CAAA;AACxE,CAAC;AAED,SAAS,WAAW,CAAC,EAAE,GAAG,KAAK,EAA+B;IAC5D,OAAO,KAAC,eAAe,CAAC,KAAK,iBAAW,cAAc,KAAK,KAAK,GAAI,CAAA;AACtE,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,aAAa,CAAC,EACrB,SAAS,EACT,WAAW,GAAG,IAAI,EAClB,GAAG,KAAK,EACuB;IAC/B,OAAO,CACL,KAAC,eAAe,CAAC,QAAQ,iBACb,gBAAgB,EAC1B,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,EAAE,CACX,0IAA0I,EAC1I,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,aAAa,CAAC,EACrB,IAAI,GAAG,OAAO,EACd,IAAI,GAAG,IAAI,EACX,SAAS,EACT,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EAGuC;IAC/C,OAAO,CACL,MAAC,YAAY,IAAC,SAAS,EAAE,SAAS,aAChC,KAAC,aAAa,KAAG,EACjB,KAAC,eAAe,CAAC,QAAQ,IAAC,SAAS,EAAE,sBAAsB,CAAC,EAAE,IAAI,EAAE,CAAC,YACnE,KAAC,eAAe,CAAC,KAAK,iBACV,gBAAgB,eACf,IAAI,eACJ,IAAI,EACf,SAAS,EAAE,EAAE,CAAC,mBAAmB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,KACzD,KAAK,YAER,QAAQ,GACa,GACC,IACd,CAChB,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,YAAY,CAAC,EACpB,KAAK,EACL,WAAW,EACX,UAAU,GAAG,OAAO,EACpB,eAAe,GAAG,IAAI,EACtB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EAOT;IACC,OAAO,CACL,4BACY,eAAe,EACzB,SAAS,EAAE,EAAE,CAAC,6CAA6C,EAAE,SAAS,CAAC,KACnE,KAAK,aAET,eAAK,SAAS,EAAC,wCAAwC,aACrD,KAAC,WAAW,cAAE,KAAK,GAAe,EACjC,eAAe,IAAI,CAClB,MAAC,eAAe,CAAC,KAAK,iBACV,cAAc,EACxB,MAAM,EACJ,KAAC,MAAM,IAAC,OAAO,EAAC,OAAO,EAAC,IAAI,EAAC,SAAS,EAAC,SAAS,EAAC,eAAe,GAAG,aAGrE,KAAC,SAAS,KAAG,EACb,eAAM,SAAS,EAAC,SAAS,YAAE,UAAU,GAAQ,IACvB,CACzB,IACG,EACL,WAAW,CAAC,CAAC,CAAC,KAAC,iBAAiB,cAAE,WAAW,GAAqB,CAAC,CAAC,CAAC,IAAI,EACzE,QAAQ,IACL,CACP,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CAAC,0CAA0C,EAAE,SAAS,CAAC,KAChE,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACxE,OAAO,CACL,2BACY,eAAe,EACzB,SAAS,EAAE,EAAE,CACX,2FAA2F,EAC3F,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACvE,OAAO,CACL,KAAC,eAAe,CAAC,KAAK,iBACV,cAAc,EACxB,SAAS,EAAE,EAAE,CACX,oDAAoD,EACpD,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EAC0B;IAClC,OAAO,CACL,KAAC,eAAe,CAAC,WAAW,iBAChB,oBAAoB,EAC9B,SAAS,EAAE,EAAE,CAAC,wBAAwB,EAAE,SAAS,CAAC,KAC9C,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EACL,MAAM,EACN,UAAU,EACV,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,WAAW,EACX,aAAa,EACb,mBAAmB,EACnB,sBAAsB,GACvB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudgrid-io/ui",
3
- "version": "0.27.2",
3
+ "version": "0.28.0",
4
4
  "description": "CloudGrid design system: React components, brand design tokens, Tailwind theme, self-hosted fonts.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/",
@@ -32,6 +32,7 @@
32
32
  "@base-ui/react": "^1.7.0",
33
33
  "@fontsource-variable/jetbrains-mono": "^5.3.0",
34
34
  "@fontsource-variable/manrope": "^5.3.0",
35
+ "@fontsource-variable/space-grotesk": "^5.3.0",
35
36
  "class-variance-authority": "^0.7.1",
36
37
  "clsx": "^2.1.1",
37
38
  "sonner": "^2.0.8",