@bloomkit/react 0.1.4 → 0.2.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 +181 -11
- package/dist/index.cjs +239 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.cts +29 -4
- package/dist/index.d.ts +29 -4
- package/dist/index.js +262 -57
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -259,28 +259,198 @@ const style = useBreathing({ duration: 6 });
|
|
|
259
259
|
|
|
260
260
|
## Dark Mode
|
|
261
261
|
|
|
262
|
-
|
|
262
|
+
Wrap your app with `ThemeProvider` and use the `useTheme` hook:
|
|
263
263
|
|
|
264
|
-
```
|
|
265
|
-
|
|
264
|
+
```tsx
|
|
265
|
+
import { ThemeProvider, useTheme } from "@bloomkit/react";
|
|
266
|
+
|
|
267
|
+
// Wrap your app — defaults to OS preference
|
|
268
|
+
<ThemeProvider defaultColorMode="system">
|
|
269
|
+
<App />
|
|
270
|
+
</ThemeProvider>
|
|
271
|
+
|
|
272
|
+
// Inside any component
|
|
273
|
+
function ThemeToggle() {
|
|
274
|
+
const { resolvedMode, toggleColorMode, setColorMode } = useTheme();
|
|
275
|
+
|
|
276
|
+
return (
|
|
277
|
+
<button onClick={toggleColorMode}>
|
|
278
|
+
{resolvedMode === "dark" ? "Light mode" : "Dark mode"}
|
|
279
|
+
</button>
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Or set explicitly
|
|
284
|
+
setColorMode("dark"); // force dark
|
|
285
|
+
setColorMode("light"); // force light
|
|
286
|
+
setColorMode("system"); // follow OS
|
|
266
287
|
```
|
|
267
288
|
|
|
268
|
-
|
|
289
|
+
The provider manages the `.dark` / `.light` class on `<html>` automatically and persists the user's choice to `localStorage`.
|
|
290
|
+
|
|
291
|
+
**Without the provider:** add the `dark` class or `data-theme="dark"` attribute to `<html>` manually, or let it follow the OS preference automatically (no setup needed).
|
|
269
292
|
|
|
270
|
-
##
|
|
293
|
+
## Palettes
|
|
271
294
|
|
|
272
|
-
|
|
295
|
+
Define multiple palettes and let users switch between them at runtime. Each palette can have its own light and dark mode colors, fonts, radius, and shadows.
|
|
296
|
+
|
|
297
|
+
```tsx
|
|
298
|
+
import { ThemeProvider, useTheme, type BloomPalette } from "@bloomkit/react";
|
|
299
|
+
|
|
300
|
+
const myPalettes: BloomPalette[] = [
|
|
301
|
+
{
|
|
302
|
+
name: "ocean",
|
|
303
|
+
light: {
|
|
304
|
+
"--bloom-font": "'Nunito', sans-serif",
|
|
305
|
+
"--bloom-font-display": "'Space Grotesk', sans-serif",
|
|
306
|
+
"--bloom-bg": "#F4F8FA",
|
|
307
|
+
"--bloom-surface": "#E8F0F4",
|
|
308
|
+
"--bloom-surface2": "#D4E2EA",
|
|
309
|
+
"--bloom-text": "#1A2E3A",
|
|
310
|
+
"--bloom-text-secondary": "#5E7A8C",
|
|
311
|
+
"--bloom-accent1": "#6AB8C4",
|
|
312
|
+
"--bloom-accent1-deep": "#3A96A8",
|
|
313
|
+
"--bloom-accent2": "#E0A860",
|
|
314
|
+
"--bloom-accent2-deep": "#C08840",
|
|
315
|
+
"--bloom-accent3": "#7CA0D4",
|
|
316
|
+
"--bloom-accent3-deep": "#5A80B8",
|
|
317
|
+
"--bloom-accent4": "#D47A7A",
|
|
318
|
+
"--bloom-accent4-deep": "#B85A5A",
|
|
319
|
+
},
|
|
320
|
+
dark: {
|
|
321
|
+
"--bloom-font": "'Nunito', sans-serif",
|
|
322
|
+
"--bloom-font-display": "'Space Grotesk', sans-serif",
|
|
323
|
+
"--bloom-bg": "#0E1A20",
|
|
324
|
+
"--bloom-surface": "#162228",
|
|
325
|
+
"--bloom-surface2": "#1E2E36",
|
|
326
|
+
"--bloom-text": "#D8E8EE",
|
|
327
|
+
"--bloom-text-secondary": "#7A9AAC",
|
|
328
|
+
"--bloom-accent1": "#4A9AAC",
|
|
329
|
+
"--bloom-accent1-deep": "#2A7A8C",
|
|
330
|
+
"--bloom-accent2": "#C89048",
|
|
331
|
+
"--bloom-accent2-deep": "#A87030",
|
|
332
|
+
"--bloom-accent3": "#5A80B8",
|
|
333
|
+
"--bloom-accent3-deep": "#3A60A0",
|
|
334
|
+
"--bloom-accent4": "#B85A5A",
|
|
335
|
+
"--bloom-accent4-deep": "#983A3A",
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
];
|
|
339
|
+
|
|
340
|
+
// Pass palettes to the provider
|
|
341
|
+
<ThemeProvider palettes={myPalettes}>
|
|
342
|
+
<App />
|
|
343
|
+
</ThemeProvider>
|
|
344
|
+
|
|
345
|
+
// Switch palettes from anywhere
|
|
346
|
+
function PaletteSwitcher() {
|
|
347
|
+
const { palette, setPalette, palettes } = useTheme();
|
|
348
|
+
|
|
349
|
+
return (
|
|
350
|
+
<select value={palette} onChange={(e) => setPalette(e.target.value)}>
|
|
351
|
+
{palettes.map((name) => (
|
|
352
|
+
<option key={name} value={name}>{name}</option>
|
|
353
|
+
))}
|
|
354
|
+
</select>
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
The `"bloom"` palette is always available as the default. Custom palettes override the default tokens — any token you don't specify falls back to Bloom's defaults. Both color mode and palette choice are persisted to `localStorage`.
|
|
360
|
+
|
|
361
|
+
## Theming with CSS
|
|
362
|
+
|
|
363
|
+
You can also theme with pure CSS instead of the provider — override tokens directly in your stylesheet:
|
|
364
|
+
|
|
365
|
+
### Example: "Ocean Mist" theme
|
|
273
366
|
|
|
274
367
|
```css
|
|
368
|
+
/* index.css */
|
|
369
|
+
@import "@bloomkit/react/styles.css";
|
|
370
|
+
|
|
371
|
+
/* Light mode */
|
|
275
372
|
:root {
|
|
276
|
-
|
|
277
|
-
--bloom-
|
|
278
|
-
--bloom-
|
|
279
|
-
|
|
280
|
-
|
|
373
|
+
/* Fonts */
|
|
374
|
+
--bloom-font: 'Nunito', sans-serif;
|
|
375
|
+
--bloom-font-display: 'Space Grotesk', sans-serif;
|
|
376
|
+
|
|
377
|
+
/* Surfaces */
|
|
378
|
+
--bloom-bg: #F4F8FA;
|
|
379
|
+
--bloom-surface: #E8F0F4;
|
|
380
|
+
--bloom-surface2: #D4E2EA;
|
|
381
|
+
|
|
382
|
+
/* Text */
|
|
383
|
+
--bloom-text: #1A2E3A;
|
|
384
|
+
--bloom-text-secondary: #5E7A8C;
|
|
385
|
+
|
|
386
|
+
/* Accents — success/primary (sage) */
|
|
387
|
+
--bloom-accent1: #6AB8C4;
|
|
388
|
+
--bloom-accent1-deep: #3A96A8;
|
|
389
|
+
|
|
390
|
+
/* Accents — warning (sand) */
|
|
391
|
+
--bloom-accent2: #E0A860;
|
|
392
|
+
--bloom-accent2-deep: #C08840;
|
|
393
|
+
|
|
394
|
+
/* Accents — info/accent (lavender) */
|
|
395
|
+
--bloom-accent3: #7CA0D4;
|
|
396
|
+
--bloom-accent3-deep: #5A80B8;
|
|
397
|
+
|
|
398
|
+
/* Accents — error/danger (rose) */
|
|
399
|
+
--bloom-accent4: #D47A7A;
|
|
400
|
+
--bloom-accent4-deep: #B85A5A;
|
|
401
|
+
|
|
402
|
+
/* Shadows */
|
|
403
|
+
--bloom-shadow: 0 2px 24px rgba(26, 46, 58, 0.06);
|
|
404
|
+
--bloom-shadow-hover: 0 8px 40px rgba(26, 46, 58, 0.1);
|
|
405
|
+
|
|
406
|
+
/* Shape — optional */
|
|
407
|
+
--bloom-radius-sm: 6px;
|
|
408
|
+
--bloom-radius: 10px;
|
|
409
|
+
--bloom-radius-lg: 14px;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/* Dark mode */
|
|
413
|
+
:root.dark,
|
|
414
|
+
[data-theme="dark"] {
|
|
415
|
+
--bloom-bg: #0E1A20;
|
|
416
|
+
--bloom-surface: #162228;
|
|
417
|
+
--bloom-surface2: #1E2E36;
|
|
418
|
+
--bloom-text: #D8E8EE;
|
|
419
|
+
--bloom-text-secondary: #7A9AAC;
|
|
420
|
+
--bloom-accent1: #4A9AAC;
|
|
421
|
+
--bloom-accent1-deep: #2A7A8C;
|
|
422
|
+
--bloom-accent2: #C89048;
|
|
423
|
+
--bloom-accent2-deep: #A87030;
|
|
424
|
+
--bloom-accent3: #5A80B8;
|
|
425
|
+
--bloom-accent3-deep: #3A60A0;
|
|
426
|
+
--bloom-accent4: #B85A5A;
|
|
427
|
+
--bloom-accent4-deep: #983A3A;
|
|
428
|
+
--bloom-shadow: 0 2px 24px rgba(0, 0, 0, 0.3);
|
|
429
|
+
--bloom-shadow-hover: 0 8px 40px rgba(0, 0, 0, 0.4);
|
|
281
430
|
}
|
|
282
431
|
```
|
|
283
432
|
|
|
433
|
+
### Available tokens
|
|
434
|
+
|
|
435
|
+
| Token | What it controls |
|
|
436
|
+
|-------|-----------------|
|
|
437
|
+
| `--bloom-font` | Body font family |
|
|
438
|
+
| `--bloom-font-display` | Heading/display font family |
|
|
439
|
+
| `--bloom-bg` | Page background |
|
|
440
|
+
| `--bloom-surface` | Card, input, toast backgrounds |
|
|
441
|
+
| `--bloom-surface2` | Borders, dividers, hover states |
|
|
442
|
+
| `--bloom-text` | Primary text color |
|
|
443
|
+
| `--bloom-text-secondary` | Labels, descriptions, captions |
|
|
444
|
+
| `--bloom-accent1` / `--bloom-accent1-deep` | Primary/success color (sage) |
|
|
445
|
+
| `--bloom-accent2` / `--bloom-accent2-deep` | Warning color (sand) |
|
|
446
|
+
| `--bloom-accent3` / `--bloom-accent3-deep` | Info/accent color (lavender) |
|
|
447
|
+
| `--bloom-accent4` / `--bloom-accent4-deep` | Danger/error color (rose) |
|
|
448
|
+
| `--bloom-shadow` / `--bloom-shadow-hover` | Elevation shadows |
|
|
449
|
+
| `--bloom-radius-sm` / `--bloom-radius` / `--bloom-radius-lg` / `--bloom-radius-pill` | Border radius |
|
|
450
|
+
| `--bloom-duration` / `--bloom-duration-slow` / `--bloom-duration-fast` | Animation timing |
|
|
451
|
+
| `--bloom-ease` | Easing curve |
|
|
452
|
+
| `--space-xs` through `--space-4xl` | Spacing scale |
|
|
453
|
+
|
|
284
454
|
## License
|
|
285
455
|
|
|
286
456
|
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -133,6 +133,21 @@ var buttonVariants = _classvarianceauthority.cva.call(void 0,
|
|
|
133
133
|
"bg-[var(--bloom-accent3-deep)] text-white",
|
|
134
134
|
"hover:-translate-y-[2px] hover:shadow-[var(--bloom-shadow-hover)]",
|
|
135
135
|
"active:translate-y-0 active:scale-[0.98]"
|
|
136
|
+
],
|
|
137
|
+
danger: [
|
|
138
|
+
"bg-[var(--bloom-accent4-deep)] text-white",
|
|
139
|
+
"hover:-translate-y-[2px] hover:shadow-[var(--bloom-shadow-hover)]",
|
|
140
|
+
"active:translate-y-0 active:scale-[0.98]"
|
|
141
|
+
],
|
|
142
|
+
warning: [
|
|
143
|
+
"bg-[var(--bloom-accent2-deep)] text-white",
|
|
144
|
+
"hover:-translate-y-[2px] hover:shadow-[var(--bloom-shadow-hover)]",
|
|
145
|
+
"active:translate-y-0 active:scale-[0.98]"
|
|
146
|
+
],
|
|
147
|
+
success: [
|
|
148
|
+
"bg-[var(--bloom-accent1-deep)] text-white",
|
|
149
|
+
"hover:-translate-y-[2px] hover:shadow-[var(--bloom-shadow-hover)]",
|
|
150
|
+
"active:translate-y-0 active:scale-[0.98]"
|
|
136
151
|
]
|
|
137
152
|
}
|
|
138
153
|
},
|
|
@@ -383,18 +398,18 @@ Badge.displayName = "Badge";
|
|
|
383
398
|
|
|
384
399
|
var alertVariants = _classvarianceauthority.cva.call(void 0,
|
|
385
400
|
[
|
|
386
|
-
"relative
|
|
387
|
-
"
|
|
388
|
-
"
|
|
389
|
-
"
|
|
401
|
+
"relative flex gap-[var(--space-md)] items-start",
|
|
402
|
+
"rounded-[var(--bloom-radius-lg)] p-[var(--space-lg)]",
|
|
403
|
+
"font-[family-name:var(--bloom-font)]",
|
|
404
|
+
"border"
|
|
390
405
|
],
|
|
391
406
|
{
|
|
392
407
|
variants: {
|
|
393
408
|
variant: {
|
|
394
|
-
info: "border-
|
|
395
|
-
success: "border-
|
|
396
|
-
warning: "border-
|
|
397
|
-
error: "border-
|
|
409
|
+
info: "bg-[var(--bloom-accent3)]/10 border-[var(--bloom-accent3)]/20",
|
|
410
|
+
success: "bg-[var(--bloom-accent1)]/10 border-[var(--bloom-accent1)]/20",
|
|
411
|
+
warning: "bg-[var(--bloom-accent2)]/10 border-[var(--bloom-accent2)]/20",
|
|
412
|
+
error: "bg-[var(--bloom-accent4)]/10 border-[var(--bloom-accent4)]/20"
|
|
398
413
|
}
|
|
399
414
|
},
|
|
400
415
|
defaultVariants: {
|
|
@@ -402,11 +417,40 @@ var alertVariants = _classvarianceauthority.cva.call(void 0,
|
|
|
402
417
|
}
|
|
403
418
|
}
|
|
404
419
|
);
|
|
420
|
+
var alertIconColors = {
|
|
421
|
+
info: "color-[var(--bloom-accent3-deep)]",
|
|
422
|
+
success: "color-[var(--bloom-accent1-deep)]",
|
|
423
|
+
warning: "color-[var(--bloom-accent2-deep)]",
|
|
424
|
+
error: "color-[var(--bloom-accent4-deep)]"
|
|
425
|
+
};
|
|
405
426
|
|
|
406
427
|
// src/components/alert/alert.tsx
|
|
407
428
|
|
|
429
|
+
var variantIcons = {
|
|
430
|
+
success: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
|
|
431
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "10", cy: "10", r: "9", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
432
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M6.5 10.5L8.5 12.5L13.5 7.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
433
|
+
] }),
|
|
434
|
+
error: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
|
|
435
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "10", cy: "10", r: "9", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
436
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M7.5 7.5L12.5 12.5M12.5 7.5L7.5 12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
437
|
+
] }),
|
|
438
|
+
warning: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
|
|
439
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 3L18 17H2L10 3Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinejoin: "round" }),
|
|
440
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 8.5V12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
441
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "10", cy: "14.5", r: "0.75", fill: "currentColor" })
|
|
442
|
+
] }),
|
|
443
|
+
info: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
|
|
444
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "10", cy: "10", r: "9", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
445
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 9V14", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
446
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "10", cy: "6.5", r: "0.75", fill: "currentColor" })
|
|
447
|
+
] })
|
|
448
|
+
};
|
|
408
449
|
var Alert = _react.forwardRef.call(void 0,
|
|
409
|
-
({ className, variant, ...props }, ref) => /* @__PURE__ */ _jsxruntime.
|
|
450
|
+
({ className, variant = "info", children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { ref, role: "alert", className: cn(alertVariants({ variant }), className), ...props, children: [
|
|
451
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("shrink-0 mt-px", alertIconColors[_nullishCoalesce(variant, () => ( "info"))]), children: variantIcons[_nullishCoalesce(variant, () => ( "info"))] }),
|
|
452
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 min-w-0", children })
|
|
453
|
+
] })
|
|
410
454
|
);
|
|
411
455
|
Alert.displayName = "Alert";
|
|
412
456
|
var AlertTitle = _react.forwardRef.call(void 0,
|
|
@@ -415,7 +459,7 @@ var AlertTitle = _react.forwardRef.call(void 0,
|
|
|
415
459
|
{
|
|
416
460
|
ref,
|
|
417
461
|
className: cn(
|
|
418
|
-
"font-[family-name:var(--bloom-font-display)] text-[length:var(--bloom-text-
|
|
462
|
+
"font-[family-name:var(--bloom-font-display)] text-[length:var(--bloom-text-body)] font-medium color-[var(--bloom-text)]",
|
|
419
463
|
className
|
|
420
464
|
),
|
|
421
465
|
...props
|
|
@@ -428,7 +472,7 @@ var AlertDescription = _react.forwardRef.call(void 0,
|
|
|
428
472
|
"p",
|
|
429
473
|
{
|
|
430
474
|
ref,
|
|
431
|
-
className: cn("text-[length:var(--bloom-text-
|
|
475
|
+
className: cn("text-[length:var(--bloom-text-caption)] color-[var(--bloom-text-secondary)] mt-[var(--space-xs)]", className),
|
|
432
476
|
...props
|
|
433
477
|
}
|
|
434
478
|
)
|
|
@@ -508,8 +552,9 @@ function Tooltip({ content, children, side = "top", className }) {
|
|
|
508
552
|
side,
|
|
509
553
|
sideOffset: 8,
|
|
510
554
|
className: cn(
|
|
511
|
-
"bloom z-50 rounded-[var(--bloom-radius
|
|
512
|
-
"bg-[var(--bloom-
|
|
555
|
+
"bloom z-50 rounded-[var(--bloom-radius)]",
|
|
556
|
+
"bg-[var(--bloom-surface)] color-[var(--bloom-text)]",
|
|
557
|
+
"border border-[var(--bloom-surface2)]",
|
|
513
558
|
"px-[var(--space-md)] py-[var(--space-sm)]",
|
|
514
559
|
"text-[length:var(--bloom-text-caption)] font-[family-name:var(--bloom-font)]",
|
|
515
560
|
"shadow-[var(--bloom-shadow)]",
|
|
@@ -1030,22 +1075,23 @@ function DatePicker({ value, onChange, placeholder = "Select date", className })
|
|
|
1030
1075
|
|
|
1031
1076
|
var toastVariants = _classvarianceauthority.cva.call(void 0,
|
|
1032
1077
|
[
|
|
1033
|
-
"relative flex items-
|
|
1078
|
+
"relative flex items-center gap-[var(--space-md)]",
|
|
1034
1079
|
"w-full max-w-[380px]",
|
|
1035
|
-
"rounded-[var(--bloom-radius)]",
|
|
1036
|
-
"
|
|
1080
|
+
"rounded-[var(--bloom-radius-lg)]",
|
|
1081
|
+
"p-[var(--space-lg)]",
|
|
1037
1082
|
"shadow-[var(--bloom-shadow-hover)]",
|
|
1038
|
-
"border
|
|
1083
|
+
"border",
|
|
1039
1084
|
"font-[family-name:var(--bloom-font)]",
|
|
1040
|
-
"overflow-hidden"
|
|
1085
|
+
"overflow-hidden",
|
|
1086
|
+
"animate-in fade-in-0 slide-in-from-bottom-4"
|
|
1041
1087
|
],
|
|
1042
1088
|
{
|
|
1043
1089
|
variants: {
|
|
1044
1090
|
variant: {
|
|
1045
|
-
info: "
|
|
1046
|
-
success: "
|
|
1047
|
-
warning: "
|
|
1048
|
-
error: "
|
|
1091
|
+
info: "bg-[var(--bloom-surface)] border-[var(--bloom-surface2)]",
|
|
1092
|
+
success: "bg-[var(--bloom-accent1)]/10 border-[var(--bloom-accent1)]/20",
|
|
1093
|
+
warning: "bg-[var(--bloom-accent2)]/10 border-[var(--bloom-accent2)]/20",
|
|
1094
|
+
error: "bg-[var(--bloom-accent4)]/10 border-[var(--bloom-accent4)]/20"
|
|
1049
1095
|
}
|
|
1050
1096
|
},
|
|
1051
1097
|
defaultVariants: {
|
|
@@ -1053,6 +1099,12 @@ var toastVariants = _classvarianceauthority.cva.call(void 0,
|
|
|
1053
1099
|
}
|
|
1054
1100
|
}
|
|
1055
1101
|
);
|
|
1102
|
+
var toastIconColors = {
|
|
1103
|
+
info: "color-[var(--bloom-accent3-deep)]",
|
|
1104
|
+
success: "color-[var(--bloom-accent1-deep)]",
|
|
1105
|
+
warning: "color-[var(--bloom-accent2-deep)]",
|
|
1106
|
+
error: "color-[var(--bloom-accent4-deep)]"
|
|
1107
|
+
};
|
|
1056
1108
|
|
|
1057
1109
|
// src/components/toast/toast.tsx
|
|
1058
1110
|
|
|
@@ -1077,14 +1129,36 @@ function ToastProvider({ children }) {
|
|
|
1077
1129
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bloom fixed bottom-[var(--space-xl)] right-[var(--space-xl)] z-[100] flex flex-col gap-[var(--space-md)]", children: toasts.map((t) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ToastItem, { toast: t, onDismiss: dismiss }, t.id)) })
|
|
1078
1130
|
] });
|
|
1079
1131
|
}
|
|
1132
|
+
var variantIcons2 = {
|
|
1133
|
+
success: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
|
|
1134
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "10", cy: "10", r: "9", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
1135
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M6.5 10.5L8.5 12.5L13.5 7.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
1136
|
+
] }),
|
|
1137
|
+
error: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
|
|
1138
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "10", cy: "10", r: "9", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
1139
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M7.5 7.5L12.5 12.5M12.5 7.5L7.5 12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
1140
|
+
] }),
|
|
1141
|
+
warning: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
|
|
1142
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 3L18 17H2L10 3Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinejoin: "round" }),
|
|
1143
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 8.5V12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
1144
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "10", cy: "14.5", r: "0.75", fill: "currentColor" })
|
|
1145
|
+
] }),
|
|
1146
|
+
info: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
|
|
1147
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "10", cy: "10", r: "9", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
1148
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 9V14", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
1149
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "10", cy: "6.5", r: "0.75", fill: "currentColor" })
|
|
1150
|
+
] })
|
|
1151
|
+
};
|
|
1080
1152
|
function ToastItem({ toast: t, onDismiss }) {
|
|
1081
1153
|
const duration = _nullishCoalesce(t.duration, () => ( 4e3));
|
|
1154
|
+
const variant = _nullishCoalesce(t.variant, () => ( "info"));
|
|
1082
1155
|
_react.useEffect.call(void 0, () => {
|
|
1083
1156
|
const timer = setTimeout(() => onDismiss(t.id), duration);
|
|
1084
1157
|
return () => clearTimeout(timer);
|
|
1085
1158
|
}, [t.id, duration, onDismiss]);
|
|
1086
1159
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn(toastVariants({ variant: t.variant })), children: [
|
|
1087
|
-
/* @__PURE__ */ _jsxruntime.
|
|
1160
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("shrink-0 mt-[1px]", toastIconColors[variant]), children: variantIcons2[variant] }),
|
|
1161
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0", children: [
|
|
1088
1162
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-[length:var(--bloom-text-body)] font-medium color-[var(--bloom-text)]", children: t.title }),
|
|
1089
1163
|
t.description && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-[length:var(--bloom-text-caption)] color-[var(--bloom-text-secondary)] mt-[var(--space-xs)]", children: t.description })
|
|
1090
1164
|
] }),
|
|
@@ -1092,19 +1166,10 @@ function ToastItem({ toast: t, onDismiss }) {
|
|
|
1092
1166
|
"button",
|
|
1093
1167
|
{
|
|
1094
1168
|
onClick: () => onDismiss(t.id),
|
|
1095
|
-
className: "color-[var(--bloom-text-secondary)] hover:color-[var(--bloom-text)] transition-colors shrink-0",
|
|
1169
|
+
className: "color-[var(--bloom-text-secondary)] hover:color-[var(--bloom-text)] transition-colors shrink-0 rounded-full h-[28px] w-[28px] inline-flex items-center justify-center hover:bg-[var(--bloom-surface2)]",
|
|
1096
1170
|
"aria-label": "Dismiss",
|
|
1097
1171
|
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M12 4L4 12M4 4l8 8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) })
|
|
1098
1172
|
}
|
|
1099
|
-
),
|
|
1100
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1101
|
-
"div",
|
|
1102
|
-
{
|
|
1103
|
-
className: "absolute bottom-0 left-0 h-[2px] bg-[var(--bloom-accent1-deep)]/40",
|
|
1104
|
-
style: {
|
|
1105
|
-
animation: `bloom-shrink ${duration}ms linear forwards`
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
1173
|
)
|
|
1109
1174
|
] });
|
|
1110
1175
|
}
|
|
@@ -1149,6 +1214,146 @@ var Skeleton = _react.forwardRef.call(void 0,
|
|
|
1149
1214
|
);
|
|
1150
1215
|
Skeleton.displayName = "Skeleton";
|
|
1151
1216
|
|
|
1217
|
+
// src/components/theme/theme.tsx
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
|
|
1221
|
+
|
|
1222
|
+
|
|
1223
|
+
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
|
|
1227
|
+
var ThemeContext = _react.createContext.call(void 0, null);
|
|
1228
|
+
function useTheme() {
|
|
1229
|
+
const ctx = _react.useContext.call(void 0, ThemeContext);
|
|
1230
|
+
if (!ctx) throw new Error("useTheme must be used within <ThemeProvider>");
|
|
1231
|
+
return ctx;
|
|
1232
|
+
}
|
|
1233
|
+
function getSystemPreference() {
|
|
1234
|
+
if (typeof window === "undefined") return "light";
|
|
1235
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
1236
|
+
}
|
|
1237
|
+
function resolveMode(mode) {
|
|
1238
|
+
if (mode === "system") return getSystemPreference();
|
|
1239
|
+
return mode;
|
|
1240
|
+
}
|
|
1241
|
+
function ThemeProvider({
|
|
1242
|
+
children,
|
|
1243
|
+
defaultColorMode = "system",
|
|
1244
|
+
defaultPalette = "bloom",
|
|
1245
|
+
palettes = [],
|
|
1246
|
+
storageKey = "bloom-theme"
|
|
1247
|
+
}) {
|
|
1248
|
+
const paletteMap = _react.useRef.call(void 0,
|
|
1249
|
+
new Map([
|
|
1250
|
+
["bloom", { name: "bloom" }],
|
|
1251
|
+
...palettes.map((p) => [p.name, p])
|
|
1252
|
+
])
|
|
1253
|
+
);
|
|
1254
|
+
const [colorMode, setColorModeState] = _react.useState.call(void 0, () => {
|
|
1255
|
+
if (typeof window === "undefined") return defaultColorMode;
|
|
1256
|
+
const stored = localStorage.getItem(`${storageKey}-mode`);
|
|
1257
|
+
if (stored === "light" || stored === "dark" || stored === "system") return stored;
|
|
1258
|
+
return defaultColorMode;
|
|
1259
|
+
});
|
|
1260
|
+
const [palette, setPaletteState] = _react.useState.call(void 0, () => {
|
|
1261
|
+
if (typeof window === "undefined") return defaultPalette;
|
|
1262
|
+
const stored = localStorage.getItem(`${storageKey}-palette`);
|
|
1263
|
+
if (stored && paletteMap.current.has(stored)) return stored;
|
|
1264
|
+
return defaultPalette;
|
|
1265
|
+
});
|
|
1266
|
+
const [resolvedMode, setResolvedMode] = _react.useState.call(void 0,
|
|
1267
|
+
() => resolveMode(colorMode)
|
|
1268
|
+
);
|
|
1269
|
+
const setColorMode = _react.useCallback.call(void 0,
|
|
1270
|
+
(mode) => {
|
|
1271
|
+
setColorModeState(mode);
|
|
1272
|
+
localStorage.setItem(`${storageKey}-mode`, mode);
|
|
1273
|
+
},
|
|
1274
|
+
[storageKey]
|
|
1275
|
+
);
|
|
1276
|
+
const setPalette = _react.useCallback.call(void 0,
|
|
1277
|
+
(name) => {
|
|
1278
|
+
if (!paletteMap.current.has(name)) return;
|
|
1279
|
+
setPaletteState(name);
|
|
1280
|
+
localStorage.setItem(`${storageKey}-palette`, name);
|
|
1281
|
+
},
|
|
1282
|
+
[storageKey]
|
|
1283
|
+
);
|
|
1284
|
+
const toggleColorMode = _react.useCallback.call(void 0, () => {
|
|
1285
|
+
setColorMode(resolvedMode === "light" ? "dark" : "light");
|
|
1286
|
+
}, [resolvedMode, setColorMode]);
|
|
1287
|
+
_react.useEffect.call(void 0, () => {
|
|
1288
|
+
const root = document.documentElement;
|
|
1289
|
+
const resolved = resolveMode(colorMode);
|
|
1290
|
+
setResolvedMode(resolved);
|
|
1291
|
+
root.classList.remove("light", "dark");
|
|
1292
|
+
root.classList.add(resolved);
|
|
1293
|
+
const allKeys = /* @__PURE__ */ new Set();
|
|
1294
|
+
paletteMap.current.forEach((p) => {
|
|
1295
|
+
if (p.light) Object.keys(p.light).forEach((k) => allKeys.add(k));
|
|
1296
|
+
if (p.dark) Object.keys(p.dark).forEach((k) => allKeys.add(k));
|
|
1297
|
+
});
|
|
1298
|
+
allKeys.forEach((key) => root.style.removeProperty(key));
|
|
1299
|
+
const currentPalette = paletteMap.current.get(palette);
|
|
1300
|
+
if (currentPalette) {
|
|
1301
|
+
const vars = resolved === "dark" ? currentPalette.dark : currentPalette.light;
|
|
1302
|
+
if (vars) {
|
|
1303
|
+
Object.entries(vars).forEach(([key, value]) => {
|
|
1304
|
+
root.style.setProperty(key, value);
|
|
1305
|
+
});
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
}, [colorMode, palette]);
|
|
1309
|
+
_react.useEffect.call(void 0, () => {
|
|
1310
|
+
if (colorMode !== "system") return;
|
|
1311
|
+
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
1312
|
+
const handler = () => {
|
|
1313
|
+
const resolved = resolveMode("system");
|
|
1314
|
+
setResolvedMode(resolved);
|
|
1315
|
+
const root = document.documentElement;
|
|
1316
|
+
root.classList.remove("light", "dark");
|
|
1317
|
+
root.classList.add(resolved);
|
|
1318
|
+
const allKeys = /* @__PURE__ */ new Set();
|
|
1319
|
+
paletteMap.current.forEach((p) => {
|
|
1320
|
+
if (p.light) Object.keys(p.light).forEach((k) => allKeys.add(k));
|
|
1321
|
+
if (p.dark) Object.keys(p.dark).forEach((k) => allKeys.add(k));
|
|
1322
|
+
});
|
|
1323
|
+
allKeys.forEach((key) => root.style.removeProperty(key));
|
|
1324
|
+
const currentPalette = paletteMap.current.get(palette);
|
|
1325
|
+
if (currentPalette) {
|
|
1326
|
+
const vars = resolved === "dark" ? currentPalette.dark : currentPalette.light;
|
|
1327
|
+
if (vars) {
|
|
1328
|
+
Object.entries(vars).forEach(([key, value]) => {
|
|
1329
|
+
root.style.setProperty(key, value);
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
};
|
|
1334
|
+
mq.addEventListener("change", handler);
|
|
1335
|
+
return () => mq.removeEventListener("change", handler);
|
|
1336
|
+
}, [colorMode, palette]);
|
|
1337
|
+
const paletteNames = Array.from(paletteMap.current.keys());
|
|
1338
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1339
|
+
ThemeContext.Provider,
|
|
1340
|
+
{
|
|
1341
|
+
value: {
|
|
1342
|
+
colorMode,
|
|
1343
|
+
resolvedMode,
|
|
1344
|
+
setColorMode,
|
|
1345
|
+
toggleColorMode,
|
|
1346
|
+
palette,
|
|
1347
|
+
setPalette,
|
|
1348
|
+
palettes: paletteNames
|
|
1349
|
+
},
|
|
1350
|
+
children
|
|
1351
|
+
}
|
|
1352
|
+
);
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
|
|
1356
|
+
|
|
1152
1357
|
|
|
1153
1358
|
|
|
1154
1359
|
|
|
@@ -1204,5 +1409,5 @@ Skeleton.displayName = "Skeleton";
|
|
|
1204
1409
|
|
|
1205
1410
|
|
|
1206
1411
|
|
|
1207
|
-
exports.Alert = Alert; exports.AlertDescription = AlertDescription; exports.AlertTitle = AlertTitle; exports.Avatar = Avatar; exports.AvatarGroup = AvatarGroup; exports.Badge = Badge; exports.Button = Button; exports.Card = Card; exports.CardContent = CardContent; exports.CardDescription = CardDescription; exports.CardFooter = CardFooter; exports.CardHeader = CardHeader; exports.CardTitle = CardTitle; exports.DatePicker = DatePicker; exports.Dropdown = Dropdown; exports.DropdownItem = DropdownItem; exports.DropdownSeparator = DropdownSeparator; exports.Input = Input; exports.Modal = Modal; exports.Progress = Progress; exports.ProgressCircular = ProgressCircular; exports.Skeleton = Skeleton; exports.Slider = Slider; exports.Tabs = Tabs; exports.TabsContent = TabsContent; exports.TabsList = TabsList; exports.TabsTrigger = TabsTrigger; exports.Textarea = Textarea; exports.ToastProvider = ToastProvider; exports.Toggle = Toggle; exports.Tooltip = Tooltip; exports.TooltipProvider = TooltipProvider; exports.alertVariants = alertVariants; exports.avatarVariants = avatarVariants; exports.badgeVariants = badgeVariants; exports.bloomSpring = bloomSpring; exports.bloomTransition = bloomTransition; exports.bloomTransitionFast = bloomTransitionFast; exports.bloomTransitionSlow = bloomTransitionSlow; exports.buttonVariants = buttonVariants; exports.cardHoverLift = cardHoverLift; exports.cardVariants = cardVariants; exports.cn = cn; exports.fadeIn = fadeIn; exports.hoverLift = hoverLift; exports.inputVariants = inputVariants; exports.progressFillVariants = progressFillVariants; exports.progressTrackVariants = progressTrackVariants; exports.skeletonVariants = skeletonVariants; exports.slideUp = slideUp; exports.tabsListVariants = tabsListVariants; exports.toastVariants = toastVariants; exports.useBreathing = useBreathing; exports.useReducedMotion = useReducedMotion; exports.useToast = useToast;
|
|
1412
|
+
exports.Alert = Alert; exports.AlertDescription = AlertDescription; exports.AlertTitle = AlertTitle; exports.Avatar = Avatar; exports.AvatarGroup = AvatarGroup; exports.Badge = Badge; exports.Button = Button; exports.Card = Card; exports.CardContent = CardContent; exports.CardDescription = CardDescription; exports.CardFooter = CardFooter; exports.CardHeader = CardHeader; exports.CardTitle = CardTitle; exports.DatePicker = DatePicker; exports.Dropdown = Dropdown; exports.DropdownItem = DropdownItem; exports.DropdownSeparator = DropdownSeparator; exports.Input = Input; exports.Modal = Modal; exports.Progress = Progress; exports.ProgressCircular = ProgressCircular; exports.Skeleton = Skeleton; exports.Slider = Slider; exports.Tabs = Tabs; exports.TabsContent = TabsContent; exports.TabsList = TabsList; exports.TabsTrigger = TabsTrigger; exports.Textarea = Textarea; exports.ThemeProvider = ThemeProvider; exports.ToastProvider = ToastProvider; exports.Toggle = Toggle; exports.Tooltip = Tooltip; exports.TooltipProvider = TooltipProvider; exports.alertVariants = alertVariants; exports.avatarVariants = avatarVariants; exports.badgeVariants = badgeVariants; exports.bloomSpring = bloomSpring; exports.bloomTransition = bloomTransition; exports.bloomTransitionFast = bloomTransitionFast; exports.bloomTransitionSlow = bloomTransitionSlow; exports.buttonVariants = buttonVariants; exports.cardHoverLift = cardHoverLift; exports.cardVariants = cardVariants; exports.cn = cn; exports.fadeIn = fadeIn; exports.hoverLift = hoverLift; exports.inputVariants = inputVariants; exports.progressFillVariants = progressFillVariants; exports.progressTrackVariants = progressTrackVariants; exports.skeletonVariants = skeletonVariants; exports.slideUp = slideUp; exports.tabsListVariants = tabsListVariants; exports.toastVariants = toastVariants; exports.useBreathing = useBreathing; exports.useReducedMotion = useReducedMotion; exports.useTheme = useTheme; exports.useToast = useToast;
|
|
1208
1413
|
//# sourceMappingURL=index.cjs.map
|