@marigold/system 17.1.0 → 17.2.1

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/dist/index.cjs CHANGED
@@ -1,18 +1,12 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1
2
  let react = require("react");
2
- let class_variance_authority = require("class-variance-authority");
3
+ let cva = require("cva");
3
4
  let tailwind_merge = require("tailwind-merge");
4
5
  let react_jsx_runtime = require("react/jsx-runtime");
5
- let __react_aria_i18n = require("@react-aria/i18n");
6
+ let _react_aria_i18n = require("@react-aria/i18n");
6
7
 
7
8
  //#region src/utils/className.utils.ts
8
- const cva = (base, config) => {
9
- function styles(props) {
10
- return (0, tailwind_merge.twMerge)((0, class_variance_authority.cva)(base, config)(props));
11
- }
12
- styles.variants = config?.variants;
13
- return styles;
14
- };
15
- const cn = (...inputs) => (0, tailwind_merge.twMerge)((0, class_variance_authority.cx)(inputs));
9
+ const { cva: cva$1, cx: cn, compose } = (0, cva.defineConfig)({ hooks: { onComplete: (className) => (0, tailwind_merge.twMerge)(className) } });
16
10
 
17
11
  //#endregion
18
12
  //#region src/utils/css-variables.utils.ts
@@ -118,7 +112,7 @@ const SVG = (0, react.forwardRef)(({ size = 24, children, className, color, ...p
118
112
  //#endregion
119
113
  //#region src/components/Formatters/DateFormat.tsx
120
114
  const DateFormat = ({ value, tabular, ...props }) => {
121
- const formatter = (0, __react_aria_i18n.useDateFormatter)({ ...props });
115
+ const formatter = (0, _react_aria_i18n.useDateFormatter)({ ...props });
122
116
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
123
117
  className: tabular ? "tabular-nums" : "",
124
118
  children: Array.isArray(value) ? formatter.formatRange(value[0], value[1]) : formatter.format(value)
@@ -128,7 +122,7 @@ const DateFormat = ({ value, tabular, ...props }) => {
128
122
  //#endregion
129
123
  //#region src/components/Formatters/NumericFormat.tsx
130
124
  const NumericFormat = ({ value, tabular = true, ...props }) => {
131
- const formatter = (0, __react_aria_i18n.useNumberFormatter)({ ...props });
125
+ const formatter = (0, _react_aria_i18n.useNumberFormatter)({ ...props });
132
126
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
133
127
  className: tabular ? "tabular-nums" : void 0,
134
128
  children: Array.isArray(value) ? formatter.formatRange(value[0], value[1]) : formatter.format(value)
@@ -251,64 +245,53 @@ const useStateProps = (states) => {
251
245
 
252
246
  //#endregion
253
247
  //#region src/hooks/useSmallScreen.ts
248
+ /**
249
+ * Uses CSS Media Queries Level 4 range syntax, matching Tailwind v4's
250
+ * `max-sm:` variant. This ensures the hook returns `true` for exactly
251
+ * the screen widths where `max-sm:` styles apply.
252
+ */
253
+ const smallScreenQuery = `(width < ${defaultTheme.screens.sm})`;
254
254
  const useSmallScreen = () => {
255
- const getMatches = () => {
255
+ const [matches, setMatches] = (0, react.useState)(() => {
256
256
  if (typeof window == "undefined") return false;
257
- return window.matchMedia("(max-width: 600px)").matches;
258
- };
259
- const [matches, setMatches] = (0, react.useState)(getMatches);
260
- const handleResize = (0, react.useCallback)(() => {
261
- setMatches(getMatches());
262
- }, []);
257
+ return window.matchMedia(smallScreenQuery).matches;
258
+ });
263
259
  (0, react.useEffect)(() => {
264
260
  if (typeof window == "undefined") return;
265
- window.addEventListener("resize", handleResize);
266
- return () => window.removeEventListener("resize", handleResize);
267
- }, [handleResize]);
261
+ const mediaQuery = window.matchMedia(smallScreenQuery);
262
+ const handler = (e) => setMatches(e.matches);
263
+ mediaQuery.addEventListener("change", handler);
264
+ return () => mediaQuery.removeEventListener("change", handler);
265
+ }, []);
268
266
  return matches;
269
267
  };
270
268
 
271
269
  //#endregion
272
270
  //#region src/hooks/extendTheme.tsx
271
+ /**
272
+ * Compose two style functions into one. The new function's styles
273
+ * are applied on top of the existing function's styles via `cn` (twMerge),
274
+ * so Tailwind conflicts are resolved with "new wins".
275
+ */
276
+ const composeStyleFns = (newFn, existingFn) => (props) => cn(existingFn(props), newFn(props));
273
277
  const extendTheme = (newStyles, theme) => {
274
- const mergedStyles = { ...theme.components };
275
- Object.keys(newStyles).forEach((component) => {
276
- const componentStyles = newStyles[component];
277
- const mergedComponentStyles = mergedStyles[component];
278
- if (!mergedComponentStyles) return mergedStyles;
279
- if (typeof newStyles[component] !== "function") mergedStyles[component] = Object.keys(componentStyles).reduce((acc, slot) => {
280
- const newSlot = componentStyles[slot];
281
- const mergedSlot = mergedComponentStyles[slot];
282
- const variants = ["size", "variant"].reduce((acc$1, variantItem) => {
283
- acc$1[variantItem] = {
284
- ...newSlot?.variants?.[variantItem],
285
- ...mergedSlot?.variants?.[variantItem]
286
- };
287
- return acc$1;
288
- }, {});
289
- acc[slot] = cva([mergedSlot(), newSlot()], { variants });
290
- return acc;
291
- }, { ...mergedComponentStyles });
278
+ const mergedComponents = { ...theme.components };
279
+ for (const key of Object.keys(newStyles)) {
280
+ const component = key;
281
+ const existing = mergedComponents[component];
282
+ if (!existing) continue;
283
+ const incoming = newStyles[component];
284
+ if (typeof incoming === "function") mergedComponents[component] = composeStyleFns(incoming, existing);
292
285
  else {
293
- const variants = ["size", "variant"].reduce((acc, variantItem) => {
294
- const newStylesVariants = newStyles[component].variants?.[variantItem];
295
- const mergedStylesVariants = mergedStyles[component].variants?.[variantItem];
296
- if (newStylesVariants && mergedStylesVariants) {
297
- const dupVariants = Object.keys(newStylesVariants).filter((variant) => Object.keys(mergedStylesVariants).includes(variant));
298
- if (dupVariants.length) throw new Error(dupVariants.join() + " already exists!");
299
- }
300
- acc[variantItem] = {
301
- ...newStyles[component].variants?.[variantItem],
302
- ...mergedStyles[component].variants?.[variantItem]
303
- };
304
- return acc;
305
- }, {});
306
- mergedStyles[component] = cva([mergedComponentStyles(), componentStyles()], { variants });
286
+ const existingSlots = existing;
287
+ const merged = { ...existingSlots };
288
+ for (const slot of Object.keys(incoming)) merged[slot] = composeStyleFns(incoming[slot], existingSlots[slot]);
289
+ mergedComponents[component] = merged;
307
290
  }
308
- });
291
+ }
309
292
  return {
310
293
  ...theme,
311
- components: { ...mergedStyles }
294
+ components: { ...mergedComponents }
312
295
  };
313
296
  };
314
297
 
@@ -615,12 +598,7 @@ const gapSpace = {
615
598
  64: "gap-64",
616
599
  72: "gap-72",
617
600
  80: "gap-80",
618
- 96: "gap-96",
619
- section: "gap-[var(--spacing-section)]",
620
- fieldY: "gap-[var(--spacing-fieldY)]",
621
- fieldX: "gap-[var(--spacing-fieldX)]",
622
- container: "gap-[var(--spacing-container)]",
623
- group: "gap-[var(--spacing-group)]"
601
+ 96: "gap-96"
624
602
  };
625
603
  const paddingSpace = {
626
604
  0: "p-0",
@@ -728,12 +706,7 @@ const paddingSpaceY = {
728
706
  64: "py-64",
729
707
  72: "py-72",
730
708
  80: "py-80",
731
- 96: "py-96",
732
- section: "py-[var(--spacing-section)]",
733
- fieldY: "py-[var(--spacing-field-Y)]",
734
- fieldX: "py-[var(--spacing-field-X)]",
735
- container: "py-[var(--spacing-container)]",
736
- group: "py-[var(--spacing-group)]"
709
+ 96: "py-96"
737
710
  };
738
711
  const paddingRight = {
739
712
  0: "pr-0",
@@ -996,7 +969,7 @@ exports.createSpacingVar = createSpacingVar;
996
969
  exports.createVar = createVar;
997
970
  exports.createWidthVar = createWidthVar;
998
971
  exports.cursorStyle = cursorStyle;
999
- exports.cva = cva;
972
+ exports.cva = cva$1;
1000
973
  exports.defaultTheme = defaultTheme;
1001
974
  exports.ensureCssVar = ensureCssVar;
1002
975
  exports.extendTheme = extendTheme;
package/dist/index.d.cts CHANGED
@@ -1,10 +1,9 @@
1
- import * as react0 from "react";
1
+ import * as react from "react";
2
2
  import { CSSProperties, Context, ReactNode } from "react";
3
3
  import { HtmlProps, KebabCase } from "@marigold/types";
4
4
  import * as react_jsx_runtime0 from "react/jsx-runtime";
5
5
  import { DateFormatterOptions, useNumberFormatter } from "@react-aria/i18n";
6
- import { ClassProp, ClassValue, StringToBoolean } from "class-variance-authority/dist/types";
7
- import { VariantProps } from "class-variance-authority";
6
+ import { ClassValue, VariantProps } from "cva";
8
7
 
9
8
  //#region src/components/SVG/SVG.d.ts
10
9
  interface SVGProps extends Omit<HtmlProps<'svg'>, 'fill' | 'style'> {
@@ -17,7 +16,7 @@ interface SVGProps extends Omit<HtmlProps<'svg'>, 'fill' | 'style'> {
17
16
  */
18
17
  className?: string;
19
18
  }
20
- declare const SVG: react0.ForwardRefExoticComponent<SVGProps & react0.RefAttributes<SVGSVGElement>>;
19
+ declare const SVG: react.ForwardRefExoticComponent<SVGProps & react.RefAttributes<SVGSVGElement>>;
21
20
  //#endregion
22
21
  //#region src/components/Formatters/DateFormat.d.ts
23
22
  interface DateFormatProps extends DateFormatterOptions {
@@ -62,20 +61,7 @@ declare const NumericFormat: ({
62
61
  }: NumericFormatProps) => react_jsx_runtime0.JSX.Element;
63
62
  //#endregion
64
63
  //#region src/utils/className.utils.d.ts
65
- type ConfigSchema = Record<string, Record<string, ClassValue>>;
66
- type ConfigVariants<T extends ConfigSchema> = { [Variant in keyof T]?: StringToBoolean<keyof T[Variant]> | null | undefined };
67
- type ConfigVariantsMulti<T extends ConfigSchema> = { [Variant in keyof T]?: StringToBoolean<keyof T[Variant]> | StringToBoolean<keyof T[Variant]>[] | undefined };
68
- type Config<T> = T extends ConfigSchema ? {
69
- variants?: T;
70
- defaultVariants?: ConfigVariants<T>;
71
- compoundVariants?: (T extends ConfigSchema ? (ConfigVariants<T> | ConfigVariantsMulti<T>) & ClassProp : ClassProp)[];
72
- } : never;
73
- type Props<T> = T extends ConfigSchema ? ConfigVariants<T> & ClassProp : ClassProp;
74
- declare const cva: <T>(base?: ClassValue, config?: Config<T>) => {
75
- (props?: Props<T>): string;
76
- variants: T | undefined;
77
- };
78
- declare const cn: (...inputs: ClassValue[]) => string;
64
+ declare const cva: cva.CVA, cn: cva.CX, compose: cva.Compose;
79
65
  //#endregion
80
66
  //#region src/types/theme.d.ts
81
67
  interface NestedStringObject {
@@ -89,7 +75,6 @@ interface ComponentStyleFunction<Variants extends string = never, Sizes extends
89
75
  size?: Sizes | null;
90
76
  className?: ClassValue;
91
77
  } & Partial<Additional>): string;
92
- variants: ConfigSchema | undefined;
93
78
  }
94
79
  type Theme = {
95
80
  name: string;
@@ -102,7 +87,7 @@ type Theme = {
102
87
  root?: ComponentStyleFunction;
103
88
  components: {
104
89
  Accordion?: Record<'container' | 'item' | 'header' | 'panel' | 'content' | 'icon', ComponentStyleFunction<string, string>>;
105
- ActionBar?: Record<'container' | 'count' | 'actions' | 'clearButton', ComponentStyleFunction<string, string>>;
90
+ ActionBar?: Record<'container' | 'selection' | 'count' | 'toolbar' | 'clearButton' | 'actionButton', ComponentStyleFunction<string, string>>;
106
91
  Badge?: ComponentStyleFunction<string, string>;
107
92
  Breadcrumbs?: Record<'container' | 'item' | 'link' | 'current', ComponentStyleFunction<string, string>>;
108
93
  Button?: ComponentStyleFunction<string, string>;
@@ -145,7 +130,7 @@ type Theme = {
145
130
  TextArea?: ComponentStyleFunction<string, string>;
146
131
  Tooltip?: Record<'container' | 'arrow', ComponentStyleFunction<string, string>>;
147
132
  Toast?: Record<'toast' | 'title' | 'description' | 'closeButton' | 'icon' | 'content' | 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'top' | 'bottom' | 'action', ComponentStyleFunction<string, string>>;
148
- Tabs?: Record<'container' | 'tabsList' | 'tabpanel' | 'tab', ComponentStyleFunction<string, string>>;
133
+ Tabs?: Record<'container' | 'tabsList' | 'tabpanel' | 'tab' | 'tabIndicator', ComponentStyleFunction<string, string>>;
149
134
  Underlay?: ComponentStyleFunction<string, string>;
150
135
  Calendar?: Record<'calendar' | 'calendarContainer' | 'calendarMonth' | 'calendarListboxButton' | 'calendarCell' | 'calendarControllers' | 'calendarHeader' | 'calendarGrid' | 'select', ComponentStyleFunction<string, string>>;
151
136
  DatePicker?: ComponentStyleFunction<string, string>;
@@ -155,6 +140,8 @@ type Theme = {
155
140
  FileField?: Record<'container' | 'dropZone' | 'dropZoneContent' | 'dropZoneLabel' | 'item' | 'itemLabel' | 'itemDescription' | 'itemRemove', ComponentStyleFunction<string, string>>;
156
141
  EmptyState?: Record<'container' | 'title' | 'description' | 'action', ComponentStyleFunction<string, string>>;
157
142
  ToggleButton?: Record<'group' | 'button', ComponentStyleFunction<string, string>>;
143
+ Sidebar?: Record<'root' | 'overlay' | 'modal' | 'closeButton' | 'header' | 'nav' | 'footer' | 'toggle' | 'separator' | 'groupLabel' | 'navPanel' | 'navLink' | 'backButton' | 'content', ComponentStyleFunction<string, string>>;
144
+ TopNavigation?: Record<'container' | 'start' | 'middle' | 'end', ComponentStyleFunction<string, string>>;
158
145
  };
159
146
  };
160
147
  type ComponentNames = keyof Theme['components'];
@@ -233,7 +220,7 @@ type StylesProps = { [K in keyof Theme['components']]: Partial<Theme['components
233
220
  declare const extendTheme: (newStyles: StylesProps, theme: Theme) => {
234
221
  components: {
235
222
  Accordion?: Record<"container" | "item" | "header" | "panel" | "content" | "icon", ComponentStyleFunction<string, string>>;
236
- ActionBar?: Record<"container" | "count" | "actions" | "clearButton", ComponentStyleFunction<string, string>>;
223
+ ActionBar?: Record<"container" | "selection" | "count" | "toolbar" | "clearButton" | "actionButton", ComponentStyleFunction<string, string>>;
237
224
  Badge?: ComponentStyleFunction<string, string>;
238
225
  Breadcrumbs?: Record<"container" | "item" | "link" | "current", ComponentStyleFunction<string, string>>;
239
226
  Button?: ComponentStyleFunction<string, string>;
@@ -276,7 +263,7 @@ declare const extendTheme: (newStyles: StylesProps, theme: Theme) => {
276
263
  TextArea?: ComponentStyleFunction<string, string>;
277
264
  Tooltip?: Record<"container" | "arrow", ComponentStyleFunction<string, string>>;
278
265
  Toast?: Record<"toast" | "title" | "description" | "closeButton" | "icon" | "content" | "bottom-left" | "bottom-right" | "top-left" | "top-right" | "top" | "bottom" | "action", ComponentStyleFunction<string, string>>;
279
- Tabs?: Record<"container" | "tabsList" | "tabpanel" | "tab", ComponentStyleFunction<string, string>>;
266
+ Tabs?: Record<"container" | "tabsList" | "tabpanel" | "tab" | "tabIndicator", ComponentStyleFunction<string, string>>;
280
267
  Underlay?: ComponentStyleFunction<string, string>;
281
268
  Calendar?: Record<"calendar" | "calendarContainer" | "calendarMonth" | "calendarListboxButton" | "calendarCell" | "calendarControllers" | "calendarHeader" | "calendarGrid" | "select", ComponentStyleFunction<string, string>>;
282
269
  DatePicker?: ComponentStyleFunction<string, string>;
@@ -286,6 +273,8 @@ declare const extendTheme: (newStyles: StylesProps, theme: Theme) => {
286
273
  FileField?: Record<"container" | "dropZone" | "dropZoneContent" | "dropZoneLabel" | "item" | "itemLabel" | "itemDescription" | "itemRemove", ComponentStyleFunction<string, string>>;
287
274
  EmptyState?: Record<"container" | "title" | "description" | "action", ComponentStyleFunction<string, string>>;
288
275
  ToggleButton?: Record<"group" | "button", ComponentStyleFunction<string, string>>;
276
+ Sidebar?: Record<"root" | "overlay" | "modal" | "closeButton" | "header" | "nav" | "footer" | "toggle" | "separator" | "groupLabel" | "navPanel" | "navLink" | "backButton" | "content", ComponentStyleFunction<string, string>>;
277
+ TopNavigation?: Record<"container" | "start" | "middle" | "end", ComponentStyleFunction<string, string>>;
289
278
  };
290
279
  name: string;
291
280
  screens?: {
@@ -306,7 +295,7 @@ declare const extendTheme: (newStyles: StylesProps, theme: Theme) => {
306
295
  * arbitrary pixel values, allowing interfaces to adapt gracefully across different
307
296
  * contexts and density settings.
308
297
  */
309
- type SpacingTokens = 'joined' | 'tight' | 'related' | 'peer' | 'group' | 'section' | 'context';
298
+ type SpacingTokens = 'tight' | 'related' | 'regular' | 'group' | 'section';
310
299
  //#endregion
311
300
  //#region src/defaultTheme.d.ts
312
301
  declare const defaultTheme: {
@@ -716,11 +705,6 @@ declare const gapSpace: {
716
705
  readonly 72: "gap-72";
717
706
  readonly 80: "gap-80";
718
707
  readonly 96: "gap-96";
719
- readonly section: "gap-[var(--spacing-section)]";
720
- readonly fieldY: "gap-[var(--spacing-fieldY)]";
721
- readonly fieldX: "gap-[var(--spacing-fieldX)]";
722
- readonly container: "gap-[var(--spacing-container)]";
723
- readonly group: "gap-[var(--spacing-group)]";
724
708
  };
725
709
  declare const paddingSpace: {
726
710
  readonly 0: "p-0";
@@ -829,11 +813,6 @@ declare const paddingSpaceY: {
829
813
  readonly 72: "py-72";
830
814
  readonly 80: "py-80";
831
815
  readonly 96: "py-96";
832
- readonly section: "py-[var(--spacing-section)]";
833
- readonly fieldY: "py-[var(--spacing-field-Y)]";
834
- readonly fieldX: "py-[var(--spacing-field-X)]";
835
- readonly container: "py-[var(--spacing-container)]";
836
- readonly group: "py-[var(--spacing-group)]";
837
816
  };
838
817
  declare const paddingRight: {
839
818
  readonly 0: "pr-0";
@@ -1227,4 +1206,4 @@ type SpaceProp<T extends string = ''> = {
1227
1206
  */
1228
1207
  declare const get: (obj: object, path: string, fallback?: any) => any;
1229
1208
  //#endregion
1230
- export { type AlignmentProp, type AspectProp, type ClassValue, type ComponentClassNames, type ComponentNames, type ComponentState, type ComponentStyleFunction, type Config, type ConfigSchema, type ConfigVariants, type ConfigVariantsMulti, type CursorProp, DateFormat, type DateFormatProps, type FontSizeProp, type FontStyleProp, type FontWeightProp, type GapSpaceProp, type HeightProp, type LineHeightProp, type MaxWidthProp, type NestedStringObject, type NumerFormatterOptions, NumericFormat, type NumericFormatProps, type PaddingBottomProp, type PaddingLeftProp, type PaddingRightProp, type PaddingSpaceProp, type PaddingSpacePropX, type PaddingSpacePropY, type PaddingTopProp, type PlaceItemsProp, type Props, SVG, type SVGProps, type Scale, type ScaleValue, type SpaceProp, type SpacingTokens, type StateAttrKeyProps, type StateAttrProps, type StylesProps, type TextAlignProp, type TextWrapProp, type Theme, type ThemeComponent, type ThemeComponentParts, ThemeProvider, type ThemeProviderProps, type UseClassNamesProps, type UseStateProps, type VariantProps, type VerticalAlignProp, type WhiteSpaceProps, type WidthProp, alignment, aspect, cn, createSpacingVar, createVar, createWidthVar, cursorStyle, cva, defaultTheme, ensureCssVar, extendTheme, fontWeight, gapSpace, get, height, isFraction, isScale, isValidCssCustomPropertyName, lineHeight, maxWidth, paddingBottom, paddingLeft, paddingRight, paddingSpace, paddingSpaceX, paddingSpaceY, paddingTop, placeItems, textAlign, textSize, textStyle, textWrap, useClassNames, useResponsiveValue, useSmallScreen, useStateProps, useTheme, verticalAlign, whiteSpace, width };
1209
+ export { type AlignmentProp, type AspectProp, type ClassValue, type ComponentClassNames, type ComponentNames, type ComponentState, type ComponentStyleFunction, type CursorProp, DateFormat, type DateFormatProps, type FontSizeProp, type FontStyleProp, type FontWeightProp, type GapSpaceProp, type HeightProp, type LineHeightProp, type MaxWidthProp, type NestedStringObject, type NumerFormatterOptions, NumericFormat, type NumericFormatProps, type PaddingBottomProp, type PaddingLeftProp, type PaddingRightProp, type PaddingSpaceProp, type PaddingSpacePropX, type PaddingSpacePropY, type PaddingTopProp, type PlaceItemsProp, SVG, type SVGProps, type Scale, type ScaleValue, type SpaceProp, type SpacingTokens, type StateAttrKeyProps, type StateAttrProps, type StylesProps, type TextAlignProp, type TextWrapProp, type Theme, type ThemeComponent, type ThemeComponentParts, ThemeProvider, type ThemeProviderProps, type UseClassNamesProps, type UseStateProps, type VariantProps, type VerticalAlignProp, type WhiteSpaceProps, type WidthProp, alignment, aspect, cn, createSpacingVar, createVar, createWidthVar, cursorStyle, cva, defaultTheme, ensureCssVar, extendTheme, fontWeight, gapSpace, get, height, isFraction, isScale, isValidCssCustomPropertyName, lineHeight, maxWidth, paddingBottom, paddingLeft, paddingRight, paddingSpace, paddingSpaceX, paddingSpaceY, paddingTop, placeItems, textAlign, textSize, textStyle, textWrap, useClassNames, useResponsiveValue, useSmallScreen, useStateProps, useTheme, verticalAlign, whiteSpace, width };
package/dist/index.d.mts CHANGED
@@ -1,10 +1,9 @@
1
- import * as react0 from "react";
1
+ import * as react from "react";
2
2
  import { CSSProperties, Context, ReactNode } from "react";
3
- import { VariantProps } from "class-variance-authority";
3
+ import { ClassValue, VariantProps } from "cva";
4
4
  import * as react_jsx_runtime0 from "react/jsx-runtime";
5
5
  import { DateFormatterOptions, useNumberFormatter } from "@react-aria/i18n";
6
6
  import { HtmlProps, KebabCase } from "@marigold/types";
7
- import { ClassProp, ClassValue, StringToBoolean } from "class-variance-authority/dist/types";
8
7
 
9
8
  //#region src/components/SVG/SVG.d.ts
10
9
  interface SVGProps extends Omit<HtmlProps<'svg'>, 'fill' | 'style'> {
@@ -17,7 +16,7 @@ interface SVGProps extends Omit<HtmlProps<'svg'>, 'fill' | 'style'> {
17
16
  */
18
17
  className?: string;
19
18
  }
20
- declare const SVG: react0.ForwardRefExoticComponent<SVGProps & react0.RefAttributes<SVGSVGElement>>;
19
+ declare const SVG: react.ForwardRefExoticComponent<SVGProps & react.RefAttributes<SVGSVGElement>>;
21
20
  //#endregion
22
21
  //#region src/components/Formatters/DateFormat.d.ts
23
22
  interface DateFormatProps extends DateFormatterOptions {
@@ -62,20 +61,7 @@ declare const NumericFormat: ({
62
61
  }: NumericFormatProps) => react_jsx_runtime0.JSX.Element;
63
62
  //#endregion
64
63
  //#region src/utils/className.utils.d.ts
65
- type ConfigSchema = Record<string, Record<string, ClassValue>>;
66
- type ConfigVariants<T extends ConfigSchema> = { [Variant in keyof T]?: StringToBoolean<keyof T[Variant]> | null | undefined };
67
- type ConfigVariantsMulti<T extends ConfigSchema> = { [Variant in keyof T]?: StringToBoolean<keyof T[Variant]> | StringToBoolean<keyof T[Variant]>[] | undefined };
68
- type Config<T> = T extends ConfigSchema ? {
69
- variants?: T;
70
- defaultVariants?: ConfigVariants<T>;
71
- compoundVariants?: (T extends ConfigSchema ? (ConfigVariants<T> | ConfigVariantsMulti<T>) & ClassProp : ClassProp)[];
72
- } : never;
73
- type Props<T> = T extends ConfigSchema ? ConfigVariants<T> & ClassProp : ClassProp;
74
- declare const cva: <T>(base?: ClassValue, config?: Config<T>) => {
75
- (props?: Props<T>): string;
76
- variants: T | undefined;
77
- };
78
- declare const cn: (...inputs: ClassValue[]) => string;
64
+ declare const cva: cva.CVA, cn: cva.CX, compose: cva.Compose;
79
65
  //#endregion
80
66
  //#region src/types/theme.d.ts
81
67
  interface NestedStringObject {
@@ -89,7 +75,6 @@ interface ComponentStyleFunction<Variants extends string = never, Sizes extends
89
75
  size?: Sizes | null;
90
76
  className?: ClassValue;
91
77
  } & Partial<Additional>): string;
92
- variants: ConfigSchema | undefined;
93
78
  }
94
79
  type Theme = {
95
80
  name: string;
@@ -102,7 +87,7 @@ type Theme = {
102
87
  root?: ComponentStyleFunction;
103
88
  components: {
104
89
  Accordion?: Record<'container' | 'item' | 'header' | 'panel' | 'content' | 'icon', ComponentStyleFunction<string, string>>;
105
- ActionBar?: Record<'container' | 'count' | 'actions' | 'clearButton', ComponentStyleFunction<string, string>>;
90
+ ActionBar?: Record<'container' | 'selection' | 'count' | 'toolbar' | 'clearButton' | 'actionButton', ComponentStyleFunction<string, string>>;
106
91
  Badge?: ComponentStyleFunction<string, string>;
107
92
  Breadcrumbs?: Record<'container' | 'item' | 'link' | 'current', ComponentStyleFunction<string, string>>;
108
93
  Button?: ComponentStyleFunction<string, string>;
@@ -145,7 +130,7 @@ type Theme = {
145
130
  TextArea?: ComponentStyleFunction<string, string>;
146
131
  Tooltip?: Record<'container' | 'arrow', ComponentStyleFunction<string, string>>;
147
132
  Toast?: Record<'toast' | 'title' | 'description' | 'closeButton' | 'icon' | 'content' | 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'top' | 'bottom' | 'action', ComponentStyleFunction<string, string>>;
148
- Tabs?: Record<'container' | 'tabsList' | 'tabpanel' | 'tab', ComponentStyleFunction<string, string>>;
133
+ Tabs?: Record<'container' | 'tabsList' | 'tabpanel' | 'tab' | 'tabIndicator', ComponentStyleFunction<string, string>>;
149
134
  Underlay?: ComponentStyleFunction<string, string>;
150
135
  Calendar?: Record<'calendar' | 'calendarContainer' | 'calendarMonth' | 'calendarListboxButton' | 'calendarCell' | 'calendarControllers' | 'calendarHeader' | 'calendarGrid' | 'select', ComponentStyleFunction<string, string>>;
151
136
  DatePicker?: ComponentStyleFunction<string, string>;
@@ -155,6 +140,8 @@ type Theme = {
155
140
  FileField?: Record<'container' | 'dropZone' | 'dropZoneContent' | 'dropZoneLabel' | 'item' | 'itemLabel' | 'itemDescription' | 'itemRemove', ComponentStyleFunction<string, string>>;
156
141
  EmptyState?: Record<'container' | 'title' | 'description' | 'action', ComponentStyleFunction<string, string>>;
157
142
  ToggleButton?: Record<'group' | 'button', ComponentStyleFunction<string, string>>;
143
+ Sidebar?: Record<'root' | 'overlay' | 'modal' | 'closeButton' | 'header' | 'nav' | 'footer' | 'toggle' | 'separator' | 'groupLabel' | 'navPanel' | 'navLink' | 'backButton' | 'content', ComponentStyleFunction<string, string>>;
144
+ TopNavigation?: Record<'container' | 'start' | 'middle' | 'end', ComponentStyleFunction<string, string>>;
158
145
  };
159
146
  };
160
147
  type ComponentNames = keyof Theme['components'];
@@ -233,7 +220,7 @@ type StylesProps = { [K in keyof Theme['components']]: Partial<Theme['components
233
220
  declare const extendTheme: (newStyles: StylesProps, theme: Theme) => {
234
221
  components: {
235
222
  Accordion?: Record<"container" | "item" | "header" | "panel" | "content" | "icon", ComponentStyleFunction<string, string>>;
236
- ActionBar?: Record<"container" | "count" | "actions" | "clearButton", ComponentStyleFunction<string, string>>;
223
+ ActionBar?: Record<"container" | "selection" | "count" | "toolbar" | "clearButton" | "actionButton", ComponentStyleFunction<string, string>>;
237
224
  Badge?: ComponentStyleFunction<string, string>;
238
225
  Breadcrumbs?: Record<"container" | "item" | "link" | "current", ComponentStyleFunction<string, string>>;
239
226
  Button?: ComponentStyleFunction<string, string>;
@@ -276,7 +263,7 @@ declare const extendTheme: (newStyles: StylesProps, theme: Theme) => {
276
263
  TextArea?: ComponentStyleFunction<string, string>;
277
264
  Tooltip?: Record<"container" | "arrow", ComponentStyleFunction<string, string>>;
278
265
  Toast?: Record<"toast" | "title" | "description" | "closeButton" | "icon" | "content" | "bottom-left" | "bottom-right" | "top-left" | "top-right" | "top" | "bottom" | "action", ComponentStyleFunction<string, string>>;
279
- Tabs?: Record<"container" | "tabsList" | "tabpanel" | "tab", ComponentStyleFunction<string, string>>;
266
+ Tabs?: Record<"container" | "tabsList" | "tabpanel" | "tab" | "tabIndicator", ComponentStyleFunction<string, string>>;
280
267
  Underlay?: ComponentStyleFunction<string, string>;
281
268
  Calendar?: Record<"calendar" | "calendarContainer" | "calendarMonth" | "calendarListboxButton" | "calendarCell" | "calendarControllers" | "calendarHeader" | "calendarGrid" | "select", ComponentStyleFunction<string, string>>;
282
269
  DatePicker?: ComponentStyleFunction<string, string>;
@@ -286,6 +273,8 @@ declare const extendTheme: (newStyles: StylesProps, theme: Theme) => {
286
273
  FileField?: Record<"container" | "dropZone" | "dropZoneContent" | "dropZoneLabel" | "item" | "itemLabel" | "itemDescription" | "itemRemove", ComponentStyleFunction<string, string>>;
287
274
  EmptyState?: Record<"container" | "title" | "description" | "action", ComponentStyleFunction<string, string>>;
288
275
  ToggleButton?: Record<"group" | "button", ComponentStyleFunction<string, string>>;
276
+ Sidebar?: Record<"root" | "overlay" | "modal" | "closeButton" | "header" | "nav" | "footer" | "toggle" | "separator" | "groupLabel" | "navPanel" | "navLink" | "backButton" | "content", ComponentStyleFunction<string, string>>;
277
+ TopNavigation?: Record<"container" | "start" | "middle" | "end", ComponentStyleFunction<string, string>>;
289
278
  };
290
279
  name: string;
291
280
  screens?: {
@@ -306,7 +295,7 @@ declare const extendTheme: (newStyles: StylesProps, theme: Theme) => {
306
295
  * arbitrary pixel values, allowing interfaces to adapt gracefully across different
307
296
  * contexts and density settings.
308
297
  */
309
- type SpacingTokens = 'joined' | 'tight' | 'related' | 'peer' | 'group' | 'section' | 'context';
298
+ type SpacingTokens = 'tight' | 'related' | 'regular' | 'group' | 'section';
310
299
  //#endregion
311
300
  //#region src/defaultTheme.d.ts
312
301
  declare const defaultTheme: {
@@ -716,11 +705,6 @@ declare const gapSpace: {
716
705
  readonly 72: "gap-72";
717
706
  readonly 80: "gap-80";
718
707
  readonly 96: "gap-96";
719
- readonly section: "gap-[var(--spacing-section)]";
720
- readonly fieldY: "gap-[var(--spacing-fieldY)]";
721
- readonly fieldX: "gap-[var(--spacing-fieldX)]";
722
- readonly container: "gap-[var(--spacing-container)]";
723
- readonly group: "gap-[var(--spacing-group)]";
724
708
  };
725
709
  declare const paddingSpace: {
726
710
  readonly 0: "p-0";
@@ -829,11 +813,6 @@ declare const paddingSpaceY: {
829
813
  readonly 72: "py-72";
830
814
  readonly 80: "py-80";
831
815
  readonly 96: "py-96";
832
- readonly section: "py-[var(--spacing-section)]";
833
- readonly fieldY: "py-[var(--spacing-field-Y)]";
834
- readonly fieldX: "py-[var(--spacing-field-X)]";
835
- readonly container: "py-[var(--spacing-container)]";
836
- readonly group: "py-[var(--spacing-group)]";
837
816
  };
838
817
  declare const paddingRight: {
839
818
  readonly 0: "pr-0";
@@ -1227,4 +1206,4 @@ type SpaceProp<T extends string = ''> = {
1227
1206
  */
1228
1207
  declare const get: (obj: object, path: string, fallback?: any) => any;
1229
1208
  //#endregion
1230
- export { type AlignmentProp, type AspectProp, type ClassValue, type ComponentClassNames, type ComponentNames, type ComponentState, type ComponentStyleFunction, type Config, type ConfigSchema, type ConfigVariants, type ConfigVariantsMulti, type CursorProp, DateFormat, type DateFormatProps, type FontSizeProp, type FontStyleProp, type FontWeightProp, type GapSpaceProp, type HeightProp, type LineHeightProp, type MaxWidthProp, type NestedStringObject, type NumerFormatterOptions, NumericFormat, type NumericFormatProps, type PaddingBottomProp, type PaddingLeftProp, type PaddingRightProp, type PaddingSpaceProp, type PaddingSpacePropX, type PaddingSpacePropY, type PaddingTopProp, type PlaceItemsProp, type Props, SVG, type SVGProps, type Scale, type ScaleValue, type SpaceProp, type SpacingTokens, type StateAttrKeyProps, type StateAttrProps, type StylesProps, type TextAlignProp, type TextWrapProp, type Theme, type ThemeComponent, type ThemeComponentParts, ThemeProvider, type ThemeProviderProps, type UseClassNamesProps, type UseStateProps, type VariantProps, type VerticalAlignProp, type WhiteSpaceProps, type WidthProp, alignment, aspect, cn, createSpacingVar, createVar, createWidthVar, cursorStyle, cva, defaultTheme, ensureCssVar, extendTheme, fontWeight, gapSpace, get, height, isFraction, isScale, isValidCssCustomPropertyName, lineHeight, maxWidth, paddingBottom, paddingLeft, paddingRight, paddingSpace, paddingSpaceX, paddingSpaceY, paddingTop, placeItems, textAlign, textSize, textStyle, textWrap, useClassNames, useResponsiveValue, useSmallScreen, useStateProps, useTheme, verticalAlign, whiteSpace, width };
1209
+ export { type AlignmentProp, type AspectProp, type ClassValue, type ComponentClassNames, type ComponentNames, type ComponentState, type ComponentStyleFunction, type CursorProp, DateFormat, type DateFormatProps, type FontSizeProp, type FontStyleProp, type FontWeightProp, type GapSpaceProp, type HeightProp, type LineHeightProp, type MaxWidthProp, type NestedStringObject, type NumerFormatterOptions, NumericFormat, type NumericFormatProps, type PaddingBottomProp, type PaddingLeftProp, type PaddingRightProp, type PaddingSpaceProp, type PaddingSpacePropX, type PaddingSpacePropY, type PaddingTopProp, type PlaceItemsProp, SVG, type SVGProps, type Scale, type ScaleValue, type SpaceProp, type SpacingTokens, type StateAttrKeyProps, type StateAttrProps, type StylesProps, type TextAlignProp, type TextWrapProp, type Theme, type ThemeComponent, type ThemeComponentParts, ThemeProvider, type ThemeProviderProps, type UseClassNamesProps, type UseStateProps, type VariantProps, type VerticalAlignProp, type WhiteSpaceProps, type WidthProp, alignment, aspect, cn, createSpacingVar, createVar, createWidthVar, cursorStyle, cva, defaultTheme, ensureCssVar, extendTheme, fontWeight, gapSpace, get, height, isFraction, isScale, isValidCssCustomPropertyName, lineHeight, maxWidth, paddingBottom, paddingLeft, paddingRight, paddingSpace, paddingSpaceX, paddingSpaceY, paddingTop, placeItems, textAlign, textSize, textStyle, textWrap, useClassNames, useResponsiveValue, useSmallScreen, useStateProps, useTheme, verticalAlign, whiteSpace, width };
package/dist/index.mjs CHANGED
@@ -1,18 +1,11 @@
1
- import { createContext, forwardRef, useCallback, useContext, useEffect, useMemo, useState } from "react";
2
- import { cva as cva$1, cx } from "class-variance-authority";
1
+ import { createContext, forwardRef, useContext, useEffect, useMemo, useState } from "react";
2
+ import { defineConfig } from "cva";
3
3
  import { twMerge } from "tailwind-merge";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  import { useDateFormatter, useNumberFormatter } from "@react-aria/i18n";
6
6
 
7
7
  //#region src/utils/className.utils.ts
8
- const cva = (base, config) => {
9
- function styles(props) {
10
- return twMerge(cva$1(base, config)(props));
11
- }
12
- styles.variants = config?.variants;
13
- return styles;
14
- };
15
- const cn = (...inputs) => twMerge(cx(inputs));
8
+ const { cva, cx: cn, compose } = defineConfig({ hooks: { onComplete: (className) => twMerge(className) } });
16
9
 
17
10
  //#endregion
18
11
  //#region src/utils/css-variables.utils.ts
@@ -251,64 +244,53 @@ const useStateProps = (states) => {
251
244
 
252
245
  //#endregion
253
246
  //#region src/hooks/useSmallScreen.ts
247
+ /**
248
+ * Uses CSS Media Queries Level 4 range syntax, matching Tailwind v4's
249
+ * `max-sm:` variant. This ensures the hook returns `true` for exactly
250
+ * the screen widths where `max-sm:` styles apply.
251
+ */
252
+ const smallScreenQuery = `(width < ${defaultTheme.screens.sm})`;
254
253
  const useSmallScreen = () => {
255
- const getMatches = () => {
254
+ const [matches, setMatches] = useState(() => {
256
255
  if (typeof window == "undefined") return false;
257
- return window.matchMedia("(max-width: 600px)").matches;
258
- };
259
- const [matches, setMatches] = useState(getMatches);
260
- const handleResize = useCallback(() => {
261
- setMatches(getMatches());
262
- }, []);
256
+ return window.matchMedia(smallScreenQuery).matches;
257
+ });
263
258
  useEffect(() => {
264
259
  if (typeof window == "undefined") return;
265
- window.addEventListener("resize", handleResize);
266
- return () => window.removeEventListener("resize", handleResize);
267
- }, [handleResize]);
260
+ const mediaQuery = window.matchMedia(smallScreenQuery);
261
+ const handler = (e) => setMatches(e.matches);
262
+ mediaQuery.addEventListener("change", handler);
263
+ return () => mediaQuery.removeEventListener("change", handler);
264
+ }, []);
268
265
  return matches;
269
266
  };
270
267
 
271
268
  //#endregion
272
269
  //#region src/hooks/extendTheme.tsx
270
+ /**
271
+ * Compose two style functions into one. The new function's styles
272
+ * are applied on top of the existing function's styles via `cn` (twMerge),
273
+ * so Tailwind conflicts are resolved with "new wins".
274
+ */
275
+ const composeStyleFns = (newFn, existingFn) => (props) => cn(existingFn(props), newFn(props));
273
276
  const extendTheme = (newStyles, theme) => {
274
- const mergedStyles = { ...theme.components };
275
- Object.keys(newStyles).forEach((component) => {
276
- const componentStyles = newStyles[component];
277
- const mergedComponentStyles = mergedStyles[component];
278
- if (!mergedComponentStyles) return mergedStyles;
279
- if (typeof newStyles[component] !== "function") mergedStyles[component] = Object.keys(componentStyles).reduce((acc, slot) => {
280
- const newSlot = componentStyles[slot];
281
- const mergedSlot = mergedComponentStyles[slot];
282
- const variants = ["size", "variant"].reduce((acc$1, variantItem) => {
283
- acc$1[variantItem] = {
284
- ...newSlot?.variants?.[variantItem],
285
- ...mergedSlot?.variants?.[variantItem]
286
- };
287
- return acc$1;
288
- }, {});
289
- acc[slot] = cva([mergedSlot(), newSlot()], { variants });
290
- return acc;
291
- }, { ...mergedComponentStyles });
277
+ const mergedComponents = { ...theme.components };
278
+ for (const key of Object.keys(newStyles)) {
279
+ const component = key;
280
+ const existing = mergedComponents[component];
281
+ if (!existing) continue;
282
+ const incoming = newStyles[component];
283
+ if (typeof incoming === "function") mergedComponents[component] = composeStyleFns(incoming, existing);
292
284
  else {
293
- const variants = ["size", "variant"].reduce((acc, variantItem) => {
294
- const newStylesVariants = newStyles[component].variants?.[variantItem];
295
- const mergedStylesVariants = mergedStyles[component].variants?.[variantItem];
296
- if (newStylesVariants && mergedStylesVariants) {
297
- const dupVariants = Object.keys(newStylesVariants).filter((variant) => Object.keys(mergedStylesVariants).includes(variant));
298
- if (dupVariants.length) throw new Error(dupVariants.join() + " already exists!");
299
- }
300
- acc[variantItem] = {
301
- ...newStyles[component].variants?.[variantItem],
302
- ...mergedStyles[component].variants?.[variantItem]
303
- };
304
- return acc;
305
- }, {});
306
- mergedStyles[component] = cva([mergedComponentStyles(), componentStyles()], { variants });
285
+ const existingSlots = existing;
286
+ const merged = { ...existingSlots };
287
+ for (const slot of Object.keys(incoming)) merged[slot] = composeStyleFns(incoming[slot], existingSlots[slot]);
288
+ mergedComponents[component] = merged;
307
289
  }
308
- });
290
+ }
309
291
  return {
310
292
  ...theme,
311
- components: { ...mergedStyles }
293
+ components: { ...mergedComponents }
312
294
  };
313
295
  };
314
296
 
@@ -615,12 +597,7 @@ const gapSpace = {
615
597
  64: "gap-64",
616
598
  72: "gap-72",
617
599
  80: "gap-80",
618
- 96: "gap-96",
619
- section: "gap-[var(--spacing-section)]",
620
- fieldY: "gap-[var(--spacing-fieldY)]",
621
- fieldX: "gap-[var(--spacing-fieldX)]",
622
- container: "gap-[var(--spacing-container)]",
623
- group: "gap-[var(--spacing-group)]"
600
+ 96: "gap-96"
624
601
  };
625
602
  const paddingSpace = {
626
603
  0: "p-0",
@@ -728,12 +705,7 @@ const paddingSpaceY = {
728
705
  64: "py-64",
729
706
  72: "py-72",
730
707
  80: "py-80",
731
- 96: "py-96",
732
- section: "py-[var(--spacing-section)]",
733
- fieldY: "py-[var(--spacing-field-Y)]",
734
- fieldX: "py-[var(--spacing-field-X)]",
735
- container: "py-[var(--spacing-container)]",
736
- group: "py-[var(--spacing-group)]"
708
+ 96: "py-96"
737
709
  };
738
710
  const paddingRight = {
739
711
  0: "pr-0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marigold/system",
3
- "version": "17.1.0",
3
+ "version": "17.2.1",
4
4
  "description": "Marigold System Library",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -16,6 +16,7 @@
16
16
  "types": "./dist/index.d.ts",
17
17
  "exports": {
18
18
  ".": {
19
+ "types": "./dist/index.d.mts",
19
20
  "require": "./dist/index.js",
20
21
  "import": "./dist/index.mjs"
21
22
  },
@@ -34,11 +35,11 @@
34
35
  "directory": "packages/system"
35
36
  },
36
37
  "dependencies": {
37
- "@react-aria/i18n": "^3.12.15",
38
- "class-variance-authority": "0.7.1",
38
+ "@react-aria/i18n": "^3.12.16",
39
+ "cva": "^1.0.0-beta.1",
39
40
  "deepmerge": "4.3.1",
40
41
  "react-fast-compare": "3.2.2",
41
- "tailwind-merge": "3.4.0",
42
+ "tailwind-merge": "3.5.0",
42
43
  "@marigold/types": "1.4.0"
43
44
  },
44
45
  "peerDependencies": {
@@ -50,8 +51,8 @@
50
51
  "@types/react": "19.2.14",
51
52
  "postcss": "8.5.6",
52
53
  "react": "19.2.4",
53
- "tailwindcss": "4.1.18",
54
- "tsdown": "0.16.8",
54
+ "tailwindcss": "4.2.1",
55
+ "tsdown": "0.20.3",
55
56
  "@marigold/tsconfig": "0.4.2"
56
57
  },
57
58
  "scripts": {