@umami/react-zen 0.232.0 → 0.234.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # zen
2
2
 
3
- **zen** is a props-driven React component library built for speed. Build polished interfaces without writing HTML, CSS, or thinking about Tailwind classes.
3
+ **Zen** is a props-driven React component library built for speed. Build polished interfaces without writing HTML, CSS, or thinking about Tailwind classes.
4
4
 
5
5
  - **Props over classes** - Style through component props, not utility classes
6
6
  - **Design included** - Complete design system out of the box with dark mode
@@ -43,11 +43,11 @@ export default function Welcome() {
43
43
 
44
44
  No `className`. No CSS files. Just components and props.
45
45
 
46
- ## Why zen?
46
+ ## Why Zen?
47
47
 
48
48
  Building UI is slow. You have to think about markup, CSS organization, responsive breakpoints, accessibility, and design consistency.
49
49
 
50
- zen eliminates that friction:
50
+ Zen eliminates that friction:
51
51
 
52
52
  | Traditional approach | zen approach |
53
53
  |---------------------|--------------|
package/dist/index.d.mts CHANGED
@@ -117,6 +117,12 @@ type MinWidth = Spacing | Fraction | SizingSpecial | WidthViewport;
117
117
  type MaxWidth = Spacing | Fraction | MaxWidthSpecial | WidthViewport;
118
118
  type MinHeight = Spacing | Fraction | SizingSpecial | HeightViewport;
119
119
  type MaxHeight = Spacing | Fraction | SizingSpecial | HeightViewport;
120
+ interface StateStyles {
121
+ color?: FontColor;
122
+ backgroundColor?: BackgroundColor;
123
+ borderColor?: BorderColor;
124
+ opacity?: Opacity;
125
+ }
120
126
 
121
127
  type RenderProp<P = Record<string, unknown>> = ReactElement | ((props: P) => ReactElement);
122
128
  /**
@@ -224,6 +230,9 @@ interface BoxProps extends Omit<HTMLAttributes<HTMLElement>, 'color'> {
224
230
  order?: number;
225
231
  zIndex?: number;
226
232
  theme?: string;
233
+ hover?: StateStyles;
234
+ focus?: StateStyles;
235
+ active?: StateStyles;
227
236
  as?: string;
228
237
  render?: RenderProp<BoxRenderProps>;
229
238
  }
package/dist/index.d.ts CHANGED
@@ -117,6 +117,12 @@ type MinWidth = Spacing | Fraction | SizingSpecial | WidthViewport;
117
117
  type MaxWidth = Spacing | Fraction | MaxWidthSpecial | WidthViewport;
118
118
  type MinHeight = Spacing | Fraction | SizingSpecial | HeightViewport;
119
119
  type MaxHeight = Spacing | Fraction | SizingSpecial | HeightViewport;
120
+ interface StateStyles {
121
+ color?: FontColor;
122
+ backgroundColor?: BackgroundColor;
123
+ borderColor?: BorderColor;
124
+ opacity?: Opacity;
125
+ }
120
126
 
121
127
  type RenderProp<P = Record<string, unknown>> = ReactElement | ((props: P) => ReactElement);
122
128
  /**
@@ -224,6 +230,9 @@ interface BoxProps extends Omit<HTMLAttributes<HTMLElement>, 'color'> {
224
230
  order?: number;
225
231
  zIndex?: number;
226
232
  theme?: string;
233
+ hover?: StateStyles;
234
+ focus?: StateStyles;
235
+ active?: StateStyles;
227
236
  as?: string;
228
237
  render?: RenderProp<BoxRenderProps>;
229
238
  }
package/dist/index.js CHANGED
@@ -84,7 +84,7 @@ var button = tailwindVariants.tv({
84
84
  "pressed:bg-interactive-pressed"
85
85
  ],
86
86
  primary: [
87
- "bg-interactive-selected text-interactive-text-selected",
87
+ "bg-primary text-primary-foreground",
88
88
  "hover:opacity-90",
89
89
  "pressed:opacity-80",
90
90
  "disabled:opacity-50"
@@ -215,7 +215,7 @@ tailwindVariants.tv({
215
215
  });
216
216
  var tooltip = tailwindVariants.tv({
217
217
  base: [
218
- "bg-surface-inverted text-foreground-inverted text-base px-2 py-1 rounded",
218
+ "bg-surface-inverted text-primary-foreground text-base px-2 py-1 rounded",
219
219
  "entering:animate-popover-in",
220
220
  "exiting:animate-popover-out"
221
221
  ]
@@ -231,7 +231,7 @@ var checkbox = tailwindVariants.tv({
231
231
  "flex items-center justify-center",
232
232
  "w-5 h-5 rounded border border-edge bg-surface-base",
233
233
  "shadow-sm transition-colors",
234
- "group-selected:bg-interactive-selected group-selected:border-interactive-selected group-selected:text-interactive-text-selected",
234
+ "group-selected:bg-primary group-selected:border-primary group-selected:text-primary-foreground",
235
235
  "group-indeterminate:bg-surface-base group-indeterminate:text-foreground-primary",
236
236
  "group-disabled:bg-surface-disabled",
237
237
  "group-focus-visible:ring-2 group-focus-visible:ring-focus-ring group-focus-visible:ring-offset-1"
@@ -253,9 +253,9 @@ var switchVariant = tailwindVariants.tv({
253
253
  ],
254
254
  track: [
255
255
  "flex items-center w-10 h-6 px-1 rounded-full",
256
- "bg-track",
256
+ "bg-interactive",
257
257
  "transition-colors",
258
- "group-selected:bg-interactive-selected",
258
+ "group-selected:bg-primary",
259
259
  "group-focus-visible:ring-2 group-focus-visible:ring-focus-ring group-focus-visible:ring-offset-1"
260
260
  ],
261
261
  thumb: [
@@ -272,10 +272,10 @@ tailwindVariants.tv({
272
272
  list: ["flex gap-1 border-b border-edge-muted"],
273
273
  tab: [
274
274
  "px-4 py-2 text-base font-medium cursor-pointer",
275
- "text-foreground-secondary outline-none",
275
+ "text-foreground-muted outline-none",
276
276
  "border-b-2 border-transparent -mb-px",
277
277
  "hovered:text-foreground-primary",
278
- "selected:text-foreground-primary selected:border-edge-inverted",
278
+ "selected:text-foreground-primary selected:border-primary",
279
279
  "disabled:text-foreground-disabled disabled:cursor-default",
280
280
  "focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:ring-offset-2"
281
281
  ],
@@ -1108,10 +1108,9 @@ var shadowMap = {
1108
1108
  true: "shadow-[var(--shadow-default)]"
1109
1109
  };
1110
1110
  var semanticColorMap = {
1111
- primary: { text: "text-foreground-primary", bg: "bg-interactive-selected" },
1112
- secondary: { text: "text-foreground-secondary", bg: "bg-surface-raised" },
1111
+ primary: { text: "text-foreground-primary", bg: "bg-primary" },
1113
1112
  muted: { text: "text-foreground-muted", bg: "bg-surface-raised" },
1114
- inverted: { text: "text-foreground-inverted", bg: "bg-surface-inverted" },
1113
+ inverted: { text: "text-primary-foreground", bg: "bg-surface-inverted" },
1115
1114
  disabled: { text: "text-foreground-disabled", bg: "bg-surface-disabled" },
1116
1115
  transparent: { text: "text-transparent", bg: "bg-transparent" },
1117
1116
  true: { text: "text-foreground-primary", bg: "bg-interactive" },
@@ -1443,8 +1442,7 @@ var borderMap = {
1443
1442
  var semanticBorderColorMap = {
1444
1443
  true: "border-edge",
1445
1444
  transparent: "border-transparent",
1446
- primary: "border-edge-inverted",
1447
- inverted: "border-edge-inverted",
1445
+ primary: "border-primary",
1448
1446
  muted: "border-edge-muted",
1449
1447
  strong: "border-edge-strong",
1450
1448
  disabled: "border-edge-muted"
@@ -2284,6 +2282,37 @@ function isMinHeightPreset(value) {
2284
2282
  function isMaxHeightPreset(value) {
2285
2283
  return value in maxHeightMap;
2286
2284
  }
2285
+ function addStatePrefix(prefix, className) {
2286
+ if (!className) return "";
2287
+ return className.split(" ").filter(Boolean).map((cls) => `${prefix}:${cls}`).join(" ");
2288
+ }
2289
+ function mapStateStyles(prefix, styles) {
2290
+ if (!styles) return "";
2291
+ const classes = [];
2292
+ if (styles.color !== void 0) {
2293
+ const colorClass = mapTextColor(
2294
+ typeof styles.color === "boolean" ? "true" : String(styles.color)
2295
+ );
2296
+ if (colorClass) classes.push(addStatePrefix(prefix, colorClass));
2297
+ }
2298
+ if (styles.backgroundColor !== void 0) {
2299
+ const bgClass = mapBackgroundColor(
2300
+ typeof styles.backgroundColor === "boolean" ? "true" : String(styles.backgroundColor)
2301
+ );
2302
+ if (bgClass) classes.push(addStatePrefix(prefix, bgClass));
2303
+ }
2304
+ if (styles.borderColor !== void 0) {
2305
+ const borderClass = mapBorderColor(
2306
+ typeof styles.borderColor === "boolean" ? "true" : String(styles.borderColor)
2307
+ );
2308
+ if (borderClass) classes.push(addStatePrefix(prefix, borderClass));
2309
+ }
2310
+ if (styles.opacity !== void 0) {
2311
+ const opacityClass = mapOpacity(styles.opacity);
2312
+ if (opacityClass) classes.push(addStatePrefix(prefix, opacityClass));
2313
+ }
2314
+ return classes.join(" ");
2315
+ }
2287
2316
  var sizeMap = {
2288
2317
  xs: "w-3 h-3",
2289
2318
  sm: "w-4 h-4",
@@ -2499,6 +2528,9 @@ var Box = react.forwardRef(function Box2({
2499
2528
  order,
2500
2529
  zIndex,
2501
2530
  theme,
2531
+ hover,
2532
+ focus,
2533
+ active,
2502
2534
  as = "div",
2503
2535
  render,
2504
2536
  className,
@@ -2553,6 +2585,9 @@ var Box = react.forwardRef(function Box2({
2553
2585
  mapPointerEvents(pointerEvents),
2554
2586
  mapAlignSelf(alignSelf),
2555
2587
  theme && `${theme}-theme`,
2588
+ mapStateStyles("hover", hover),
2589
+ mapStateStyles("focus", focus),
2590
+ mapStateStyles("active", active),
2556
2591
  className
2557
2592
  );
2558
2593
  const widthStyle = getSizingStyle(width, isWidthPreset);
@@ -2759,15 +2794,7 @@ function AlertDialog({
2759
2794
  } });
2760
2795
  }
2761
2796
  function Blockquote({ className, children, ...props }) {
2762
- return /* @__PURE__ */ jsxRuntime.jsx(
2763
- Text,
2764
- {
2765
- ...props,
2766
- as: "blockquote",
2767
- className: cn("border-l-2 border-edge-inverted pl-5", className),
2768
- children
2769
- }
2770
- );
2797
+ return /* @__PURE__ */ jsxRuntime.jsx(Text, { ...props, as: "blockquote", className: cn("border-l-2 border-primary pl-5", className), children });
2771
2798
  }
2772
2799
  function Breadcrumbs({ children, className, ...props }) {
2773
2800
  return /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Breadcrumbs, { ...props, className: cn("flex items-center gap-3", className), children });
@@ -2834,7 +2861,7 @@ function Calendar({
2834
2861
  "hover:bg-interactive",
2835
2862
  "data-[outside-month]:hidden",
2836
2863
  "data-[focus-visible]:outline-2 data-[focus-visible]:outline-focus-ring data-[focus-visible]:outline-offset-2",
2837
- "data-[selected]:text-interactive-text-selected data-[selected]:bg-interactive-selected",
2864
+ "data-[selected]:text-primary-foreground data-[selected]:bg-primary",
2838
2865
  "data-[disabled]:text-foreground-disabled"
2839
2866
  ),
2840
2867
  date
@@ -3464,7 +3491,7 @@ function TableCell({ children, className, align, ...props }) {
3464
3491
  className: cn(
3465
3492
  "flex p-2 flex-1 first:pl-0 last:pr-0",
3466
3493
  "[&_a]:font-medium [&_a]:underline [&_a]:decoration-edge [&_a]:underline-offset-4",
3467
- "[&_a:hover]:decoration-edge-inverted",
3494
+ "[&_a:hover]:decoration-primary",
3468
3495
  align && alignClasses2[align],
3469
3496
  className
3470
3497
  ),
@@ -3751,13 +3778,13 @@ function Spinner(props) {
3751
3778
  ...domProps,
3752
3779
  className: cn("relative inline-flex justify-center items-center", sizeMap3[size], className),
3753
3780
  children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "25 25 50 50", className: "zen-spinner-svg w-full h-full", children: [
3754
- !quiet && /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "zen-spinner-track stroke-track", cx: "50", cy: "50", r: "20" }),
3781
+ !quiet && /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "zen-spinner-track stroke-interactive", cx: "50", cy: "50", r: "20" }),
3755
3782
  /* @__PURE__ */ jsxRuntime.jsx(
3756
3783
  "circle",
3757
3784
  {
3758
3785
  className: cn(
3759
3786
  "zen-spinner-fill",
3760
- isDisabled ? "stroke-content-disabled" : "stroke-track-fill"
3787
+ isDisabled ? "stroke-content-disabled" : "stroke-primary"
3761
3788
  ),
3762
3789
  cx: "50",
3763
3790
  cy: "50",
@@ -4482,7 +4509,16 @@ function PasswordField({ label, className, ...props }) {
4482
4509
  ] });
4483
4510
  }
4484
4511
  function Track({ children }) {
4485
- return /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "relative", borderRadius: "full", overflow: "hidden", className: "w-full h-2 bg-track", children });
4512
+ return /* @__PURE__ */ jsxRuntime.jsx(
4513
+ Box,
4514
+ {
4515
+ position: "relative",
4516
+ borderRadius: "full",
4517
+ overflow: "hidden",
4518
+ className: "w-full h-2 bg-interactive",
4519
+ children
4520
+ }
4521
+ );
4486
4522
  }
4487
4523
  function Fill({ percentage }) {
4488
4524
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -4493,7 +4529,7 @@ function Fill({ percentage }) {
4493
4529
  bottom: "0",
4494
4530
  left: "0",
4495
4531
  borderRadius: "full",
4496
- className: "bg-track-fill transition-all",
4532
+ className: "bg-primary transition-all",
4497
4533
  style: { width: `${percentage}%` }
4498
4534
  }
4499
4535
  );
@@ -4519,11 +4555,11 @@ function ProgressCircle({ className, showPercentage, ...props }) {
4519
4555
  xmlns: "http://www.w3.org/2000/svg",
4520
4556
  className: "fill-none stroke-[8px] -rotate-90 w-24 h-24",
4521
4557
  children: [
4522
- /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "stroke-track", cx: "50", cy: "50", r: "45" }),
4558
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "stroke-interactive", cx: "50", cy: "50", r: "45" }),
4523
4559
  /* @__PURE__ */ jsxRuntime.jsx(
4524
4560
  "circle",
4525
4561
  {
4526
- className: "stroke-track-fill",
4562
+ className: "stroke-primary",
4527
4563
  cx: "50",
4528
4564
  cy: "50",
4529
4565
  r: "45",
@@ -4562,7 +4598,7 @@ function Radio({ children, className, ...props }) {
4562
4598
  "radio group flex items-center gap-3 cursor-pointer text-base",
4563
4599
  "before:content-[''] before:block before:w-5 before:h-5 before:box-border before:rounded-full",
4564
4600
  "before:border before:border-edge-strong before:bg-surface-base before:transition-all before:duration-200",
4565
- "data-[selected]:before:border-[6px] data-[selected]:before:border-interactive-selected",
4601
+ "data-[selected]:before:border-[6px] data-[selected]:before:border-primary",
4566
4602
  "data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed",
4567
4603
  className
4568
4604
  ),
@@ -4806,7 +4842,7 @@ function SidebarItem({
4806
4842
  }
4807
4843
  function Fill2({ percentage }) {
4808
4844
  const width = `calc(10px + ${percentage}% - ${percentage * 0.2}px)`;
4809
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 left-0 rounded-full bg-track-fill", style: { width } });
4845
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 left-0 rounded-full bg-primary", style: { width } });
4810
4846
  }
4811
4847
  function Thumb({ percentage }) {
4812
4848
  const left = `calc(${percentage}% - ${percentage * 0.2}px)`;
@@ -4814,7 +4850,7 @@ function Thumb({ percentage }) {
4814
4850
  reactAriaComponents.SliderThumb,
4815
4851
  {
4816
4852
  className: cn(
4817
- "absolute w-5 h-5 rounded-full bg-surface-base border-2 border-edge-inverted shadow",
4853
+ "absolute w-5 h-5 rounded-full bg-surface-base border-2 border-primary shadow",
4818
4854
  "focus:outline-none focus:ring-2 focus:ring-focus-ring focus:ring-offset-2"
4819
4855
  ),
4820
4856
  style: { top: "50%", left, transform: "translateY(-50%)" }
@@ -4830,7 +4866,7 @@ function Slider({ className, showValue = true, label, ...props }) {
4830
4866
  /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.SliderTrack, { className: "relative h-5 w-full", children: ({ state }) => {
4831
4867
  const percentage = state.getThumbPercent(0) * 100;
4832
4868
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4833
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-x-0 top-1/2 -translate-y-1/2 h-1 rounded-full bg-track overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(Fill2, { percentage }) }),
4869
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-x-0 top-1/2 -translate-y-1/2 h-2 rounded-full bg-interactive overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(Fill2, { percentage }) }),
4834
4870
  /* @__PURE__ */ jsxRuntime.jsx(Thumb, { percentage })
4835
4871
  ] });
4836
4872
  } })
@@ -4897,7 +4933,7 @@ function Tab({ children, className, ...props }) {
4897
4933
  className: cn(
4898
4934
  "tab flex items-center justify-center text-base text-foreground-muted py-2 border-b-2 border-transparent select-none -mb-[2px] cursor-pointer outline-none",
4899
4935
  "data-[hovered]:text-foreground-primary",
4900
- "data-[selected]:text-foreground-primary data-[selected]:border-b-edge-inverted",
4936
+ "data-[selected]:text-foreground-primary data-[selected]:border-b-primary",
4901
4937
  "data-[disabled]:text-foreground-disabled data-[disabled]:cursor-default",
4902
4938
  className
4903
4939
  ),
@@ -5063,7 +5099,7 @@ function Toggle({ label, children, className, ...props }) {
5063
5099
  "flex items-center justify-center whitespace-nowrap gap-3 font-medium bg-interactive border border-transparent rounded p-2 relative cursor-pointer",
5064
5100
  "hover:bg-interactive-hover",
5065
5101
  "pressed:bg-interactive-pressed",
5066
- "data-[selected]:text-interactive-text-selected data-[selected]:bg-interactive-selected",
5102
+ "data-[selected]:text-primary-foreground data-[selected]:bg-primary",
5067
5103
  className
5068
5104
  ),
5069
5105
  children