@marigold/system 16.0.0 → 16.1.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.
@@ -1,38 +1,10 @@
1
- //#region rolldown:runtime
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
- key = keys[i];
11
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
- get: ((k) => from[k]).bind(null, key),
13
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
- });
15
- }
16
- return to;
17
- };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
- value: mod,
20
- enumerable: true
21
- }) : target, mod));
22
-
23
- //#endregion
24
1
  let react = require("react");
25
- react = __toESM(react);
26
2
  let class_variance_authority = require("class-variance-authority");
27
- class_variance_authority = __toESM(class_variance_authority);
28
3
  let tailwind_merge = require("tailwind-merge");
29
- tailwind_merge = __toESM(tailwind_merge);
4
+ let react_jsx_runtime = require("react/jsx-runtime");
30
5
  let __react_aria_i18n = require("@react-aria/i18n");
31
- __react_aria_i18n = __toESM(__react_aria_i18n);
32
- let react_fast_compare = require("react-fast-compare");
33
- react_fast_compare = __toESM(react_fast_compare);
34
6
 
35
- //#region src/utils.ts
7
+ //#region src/utils/className.utils.ts
36
8
  const cva = (base, config) => {
37
9
  function styles(props) {
38
10
  return (0, tailwind_merge.twMerge)((0, class_variance_authority.cva)(base, config)(props));
@@ -41,23 +13,19 @@ const cva = (base, config) => {
41
13
  return styles;
42
14
  };
43
15
  const cn = (...inputs) => (0, tailwind_merge.twMerge)((0, class_variance_authority.cx)(inputs));
44
- const createVar = (o) => Object.fromEntries(Object.entries(o).map(([name, val]) => [`--${name}`, val]));
16
+
17
+ //#endregion
18
+ //#region src/utils/css-variables.utils.ts
45
19
  /**
46
- * Safely get a dot-notated path within a nested object, with ability
47
- * to return a default if the full key path does not exist or
48
- * the value is undefined
20
+ * Checks if the provided string represents a numeric scale value.
49
21
  *
50
- * Based on: https://github.com/developit/dlv
22
+ * A scale value is defined as a string containing only digits,
23
+ * optionally followed by a decimal point and more digits (e.g., "1", "2.5").
24
+ *
25
+ * @param value - The string to test for scale format.
26
+ * @returns `true` if the string is a valid scale value, otherwise `false`.
51
27
  */
52
- const get = (obj, path, fallback) => {
53
- const key = path.split(".");
54
- let result = obj;
55
- for (let i = 0, length = key.length; i < length; i++) {
56
- if (!result) break;
57
- result = result[key[i]];
58
- }
59
- return result === void 0 ? fallback : result;
60
- };
28
+ const isScale = (value) => /^[0-9]+(\.[0-9]+)?$/.test(value);
61
29
  /**
62
30
  * Checks if a given string is a valid CSS custom property name (without the leading `--`).
63
31
  *
@@ -77,32 +45,60 @@ const isValidCssCustomPropertyName = (val) => /^[A-Za-z0-9_-]+$/.test(val);
77
45
  * If the value is not a valid custom property name, the function returns the original value.
78
46
  */
79
47
  const ensureCssVar = (val, prefix) => isValidCssCustomPropertyName(val) ? `var(--${prefix ? `${prefix}-` : ""}${val}, ${val})` : val;
48
+ /**
49
+ * Creates a CSS custom properties object from the given key-value pairs.
50
+ *
51
+ * @param o - An object with string keys and string/number/undefined values
52
+ * @returns A CSSProperties object with `--` prefixed keys
53
+ */
54
+ const createVar = (o) => Object.fromEntries(Object.entries(o).map(([name, val]) => [`--${name}`, val]));
55
+ /**
56
+ * Generates a CSS custom property for spacing that uses either a calc expression or a
57
+ * spacing variable reference.
58
+ *
59
+ * If `value` is a number (integer or decimal), uses the `--spacing` scale from Tailwind with calc().
60
+ * Otherwise, references a specific spacing variable (e.g., `--spacing-group`).
61
+ *
62
+ * @param name - The custom property name for spacing.
63
+ * @param value - Spacing value as a string (number or scale key).
64
+ * @returns Object with the CSS custom property for spacing.
65
+ */
66
+ const createSpacingVar = (name, value) => {
67
+ return { [`--${name}`]: isScale(value) ? `calc(var(--spacing) * ${value})` : `var(--spacing-${value})` };
68
+ };
80
69
 
81
70
  //#endregion
82
71
  //#region src/components/SVG/SVG.tsx
83
- const SVG = (0, react.forwardRef)(({ size = 24, children, className, color,...props }, ref) => {
84
- return /* @__PURE__ */ React.createElement("svg", {
72
+ const SVG = (0, react.forwardRef)(({ size = 24, children, className, color, ...props }, ref) => {
73
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
85
74
  ...props,
86
75
  ref,
87
76
  width: `${props.width || size}px`,
88
77
  height: `${props.height || size}px`,
89
78
  className: cn("flex-none fill-current", className),
90
- style: { color: color && ensureCssVar(color, "color") }
91
- }, children);
79
+ style: { color: color && ensureCssVar(color, "color") },
80
+ children
81
+ });
92
82
  });
93
83
 
94
84
  //#endregion
95
85
  //#region src/components/Formatters/DateFormat.tsx
96
- const DateFormat = ({ value, tabular,...props }) => {
86
+ const DateFormat = ({ value, tabular, ...props }) => {
97
87
  const formatter = (0, __react_aria_i18n.useDateFormatter)({ ...props });
98
- return /* @__PURE__ */ React.createElement("span", { className: tabular ? "tabular-nums" : "" }, Array.isArray(value) ? formatter.formatRange(value[0], value[1]) : formatter.format(value));
88
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
89
+ className: tabular ? "tabular-nums" : "",
90
+ children: Array.isArray(value) ? formatter.formatRange(value[0], value[1]) : formatter.format(value)
91
+ });
99
92
  };
100
93
 
101
94
  //#endregion
102
95
  //#region src/components/Formatters/NumericFormat.tsx
103
- const NumericFormat = ({ value, tabular = true,...props }) => {
96
+ const NumericFormat = ({ value, tabular = true, ...props }) => {
104
97
  const formatter = (0, __react_aria_i18n.useNumberFormatter)({ ...props });
105
- return /* @__PURE__ */ React.createElement("span", { className: tabular ? "tabular-nums" : void 0 }, Array.isArray(value) ? formatter.formatRange(value[0], value[1]) : formatter.format(value));
98
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
99
+ className: tabular ? "tabular-nums" : void 0,
100
+ children: Array.isArray(value) ? formatter.formatRange(value[0], value[1]) : formatter.format(value)
101
+ });
106
102
  };
107
103
 
108
104
  //#endregion
@@ -126,7 +122,13 @@ const useTheme = () => {
126
122
  return (0, react.useContext)(InternalContext);
127
123
  };
128
124
  function ThemeProvider({ theme, children, className }) {
129
- return /* @__PURE__ */ React.createElement(InternalContext.Provider, { value: theme }, /* @__PURE__ */ React.createElement("div", { className }, children));
125
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InternalContext.Provider, {
126
+ value: theme,
127
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
128
+ className,
129
+ children
130
+ })
131
+ });
130
132
  }
131
133
 
132
134
  //#endregion
@@ -160,6 +162,14 @@ const useClassNames = ({ component, className, variant, size, context: Component
160
162
  //#endregion
161
163
  //#region src/hooks/useResponsiveValue.ts
162
164
  /**
165
+ * Based on https://theme-ui.com/packages/match-media/
166
+ */
167
+ /**
168
+ * Hardcode fallback breakpoints, not make sure `useEffect`
169
+ * doesn't trigger on every render. Since it is part of the
170
+ * dependency array.
171
+ */
172
+ /**
163
173
  * Hook that can be used to return values based on the current screen size,
164
174
  * using breakpoints from the theme (`theme.breakpoints`). Note that this
165
175
  * hook is client.side only.
@@ -195,14 +205,14 @@ const toKebap = (val) => val.replace(KEBAB_REGEX, (match) => `-${match.toLocaleL
195
205
  * (e.g. `[data-hover]` and `[data-focus]`).
196
206
  */
197
207
  const useStateProps = (states) => {
198
- const statePropsRef = (0, react.useRef)({});
199
- let stateProps = {};
200
- for (let state in states) if (states[state]) {
201
- const key = `data-${toKebap(state)}`;
202
- stateProps[key] = "";
203
- }
204
- if (!(0, react_fast_compare.default)(statePropsRef.current, stateProps)) statePropsRef.current = stateProps;
205
- return statePropsRef.current;
208
+ return (0, react.useMemo)(() => {
209
+ const stateProps = {};
210
+ for (const state in states) if (states[state]) {
211
+ const key = `data-${toKebap(state)}`;
212
+ stateProps[key] = "";
213
+ }
214
+ return stateProps;
215
+ }, [states]);
206
216
  };
207
217
 
208
218
  //#endregion
@@ -212,12 +222,11 @@ const useSmallScreen = () => {
212
222
  if (typeof window == "undefined") return false;
213
223
  return window.matchMedia("(max-width: 600px)").matches;
214
224
  };
215
- const [matches, setMatches] = (0, react.useState)(getMatches());
225
+ const [matches, setMatches] = (0, react.useState)(getMatches);
216
226
  const handleResize = (0, react.useCallback)(() => {
217
227
  setMatches(getMatches());
218
228
  }, []);
219
229
  (0, react.useEffect)(() => {
220
- handleResize();
221
230
  if (typeof window == "undefined") return;
222
231
  window.addEventListener("resize", handleResize);
223
232
  return () => window.removeEventListener("resize", handleResize);
@@ -566,8 +575,8 @@ const gapSpace = {
566
575
  80: "gap-80",
567
576
  96: "gap-96",
568
577
  section: "gap-[var(--spacing-section)]",
569
- fieldY: "gap-[var(--spacing-field-Y)]",
570
- fieldX: "gap-[var(--spacing-field-X)]",
578
+ fieldY: "gap-[var(--spacing-fieldY)]",
579
+ fieldX: "gap-[var(--spacing-fieldX)]",
571
580
  container: "gap-[var(--spacing-container)]",
572
581
  group: "gap-[var(--spacing-group)]"
573
582
  };
@@ -833,7 +842,8 @@ const alignment = {
833
842
  alignmentX: {
834
843
  left: "items-start",
835
844
  center: "items-center",
836
- right: "items-end"
845
+ right: "items-end",
846
+ stretch: "items-stretch"
837
847
  },
838
848
  alignmentY: {
839
849
  top: "justify-start",
@@ -908,6 +918,25 @@ const cursorStyle = {
908
918
  zoomOut: "cursor-zoom-out"
909
919
  };
910
920
 
921
+ //#endregion
922
+ //#region src/utils/object.utils.ts
923
+ /**
924
+ * Safely get a dot-notated path within a nested object, with ability
925
+ * to return a default if the full key path does not exist or
926
+ * the value is undefined
927
+ *
928
+ * Based on: https://github.com/developit/dlv
929
+ */
930
+ const get = (obj, path, fallback) => {
931
+ const key = path.split(".");
932
+ let result = obj;
933
+ for (let i = 0, length = key.length; i < length; i++) {
934
+ if (!result) break;
935
+ result = result[key[i]];
936
+ }
937
+ return result === void 0 ? fallback : result;
938
+ };
939
+
911
940
  //#endregion
912
941
  exports.DateFormat = DateFormat;
913
942
  exports.NumericFormat = NumericFormat;
@@ -916,6 +945,7 @@ exports.ThemeProvider = ThemeProvider;
916
945
  exports.alignment = alignment;
917
946
  exports.aspect = aspect;
918
947
  exports.cn = cn;
948
+ exports.createSpacingVar = createSpacingVar;
919
949
  exports.createVar = createVar;
920
950
  exports.cursorStyle = cursorStyle;
921
951
  exports.cva = cva;
@@ -926,6 +956,7 @@ exports.fontWeight = fontWeight;
926
956
  exports.gapSpace = gapSpace;
927
957
  exports.get = get;
928
958
  exports.height = height;
959
+ exports.isScale = isScale;
929
960
  exports.isValidCssCustomPropertyName = isValidCssCustomPropertyName;
930
961
  exports.maxWidth = maxWidth;
931
962
  exports.paddingBottom = paddingBottom;
@@ -1,6 +1,7 @@
1
1
  import * as react0 from "react";
2
- import { Context, ReactNode } from "react";
2
+ import { CSSProperties, Context, ReactNode } from "react";
3
3
  import { HtmlProps, KebabCase } from "@marigold/types";
4
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
4
5
  import { DateFormatterOptions, useNumberFormatter } from "@react-aria/i18n";
5
6
  import { ClassProp, ClassValue, StringToBoolean } from "class-variance-authority/dist/types";
6
7
  import { VariantProps } from "class-variance-authority";
@@ -34,7 +35,7 @@ declare const DateFormat: ({
34
35
  value,
35
36
  tabular,
36
37
  ...props
37
- }: DateFormatProps) => react0.JSX.Element;
38
+ }: DateFormatProps) => react_jsx_runtime0.JSX.Element;
38
39
  //#endregion
39
40
  //#region src/components/Formatters/NumericFormat.d.ts
40
41
  type NumerFormatterOptions = NonNullable<Parameters<typeof useNumberFormatter>[0]>;
@@ -58,53 +59,23 @@ declare const NumericFormat: ({
58
59
  value,
59
60
  tabular,
60
61
  ...props
61
- }: NumericFormatProps) => react0.JSX.Element;
62
+ }: NumericFormatProps) => react_jsx_runtime0.JSX.Element;
62
63
  //#endregion
63
- //#region src/utils.d.ts
64
+ //#region src/utils/className.utils.d.ts
64
65
  type ConfigSchema = Record<string, Record<string, ClassValue>>;
65
- type ConfigVariants<T$1 extends ConfigSchema> = { [Variant in keyof T$1]?: StringToBoolean<keyof T$1[Variant]> | null | undefined };
66
- type ConfigVariantsMulti<T$1 extends ConfigSchema> = { [Variant in keyof T$1]?: StringToBoolean<keyof T$1[Variant]> | StringToBoolean<keyof T$1[Variant]>[] | undefined };
67
- type Config<T$1> = T$1 extends ConfigSchema ? {
68
- variants?: T$1;
69
- defaultVariants?: ConfigVariants<T$1>;
70
- compoundVariants?: (T$1 extends ConfigSchema ? (ConfigVariants<T$1> | ConfigVariantsMulti<T$1>) & ClassProp : ClassProp)[];
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)[];
71
72
  } : never;
72
- type Props<T$1> = T$1 extends ConfigSchema ? ConfigVariants<T$1> & ClassProp : ClassProp;
73
+ type Props<T> = T extends ConfigSchema ? ConfigVariants<T> & ClassProp : ClassProp;
73
74
  declare const cva: <T>(base?: ClassValue, config?: Config<T>) => {
74
75
  (props?: Props<T>): string;
75
76
  variants: T | undefined;
76
77
  };
77
78
  declare const cn: (...inputs: ClassValue[]) => string;
78
- declare const createVar: (o: {
79
- [key: string]: string | number | undefined;
80
- }) => React.CSSProperties;
81
- /**
82
- * Safely get a dot-notated path within a nested object, with ability
83
- * to return a default if the full key path does not exist or
84
- * the value is undefined
85
- *
86
- * Based on: https://github.com/developit/dlv
87
- */
88
- declare const get: (obj: object, path: string, fallback?: any) => any;
89
- /**
90
- * Checks if a given string is a valid CSS custom property name (without the leading `--`).
91
- *
92
- * This simplified check ensures:
93
- * - The name does not start with a digit.
94
- * - It contains only word characters (letters, digits, underscore) or hyphens.
95
- * - It must include at least one hyphen to be considered a custom property name.
96
- */
97
- declare const isValidCssCustomPropertyName: (val: string) => boolean;
98
- /**
99
- * Ensures that the given value is formatted as a CSS variable reference.
100
- *
101
- * If the provided value (`val`) is a valid CSS custom property name (without the leading `--`),
102
- * the function returns a string in the form of `var(--<prefix-if-provided><val>, <val>)`. When a
103
- * `prefix` is provided, it is prepended to the custom property name with a hyphen.
104
- *
105
- * If the value is not a valid custom property name, the function returns the original value.
106
- */
107
- declare const ensureCssVar: (val: string, prefix?: string) => string;
108
79
  //#endregion
109
80
  //#region src/types/theme.d.ts
110
81
  interface NestedStringObject {
@@ -180,8 +151,8 @@ type Theme = {
180
151
  };
181
152
  };
182
153
  type ComponentNames = keyof Theme['components'];
183
- type ThemeComponent<C$1 extends ComponentNames> = NonNullable<Theme['components'][C$1]>;
184
- type ThemeComponentParts<C$1 extends ComponentNames> = keyof ThemeComponent<C$1>;
154
+ type ThemeComponent<C extends ComponentNames> = NonNullable<Theme['components'][C]>;
155
+ type ThemeComponentParts<C extends ComponentNames> = keyof ThemeComponent<C>;
185
156
  //#endregion
186
157
  //#region src/hooks/useClassNames.d.ts
187
158
  interface ComponentContextProps {
@@ -189,14 +160,14 @@ interface ComponentContextProps {
189
160
  variant?: string;
190
161
  [key: string]: any;
191
162
  }
192
- interface UseClassNamesProps<C$1 extends ComponentNames> {
193
- component: C$1;
163
+ interface UseClassNamesProps<C extends ComponentNames> {
164
+ component: C;
194
165
  variant?: string;
195
166
  size?: string;
196
- className?: ThemeComponent<C$1> extends ((...args: any) => any) ? string : { [slot in keyof ThemeComponent<C$1>]?: string };
167
+ className?: ThemeComponent<C> extends ((...args: any) => any) ? string : { [slot in keyof ThemeComponent<C>]?: string };
197
168
  context?: Context<ComponentContextProps>;
198
169
  }
199
- type ComponentClassNames<C$1 extends ComponentNames> = ThemeComponent<C$1> extends ((...args: any) => any) ? string : { [slot in keyof ThemeComponent<C$1>]: string };
170
+ type ComponentClassNames<C extends ComponentNames> = ThemeComponent<C> extends ((...args: any) => any) ? string : { [slot in keyof ThemeComponent<C>]: string };
200
171
  declare const useClassNames: <C extends ComponentNames>({
201
172
  component,
202
173
  className,
@@ -227,11 +198,11 @@ declare const useStateProps: (states: UseStateProps) => StateAttrProps;
227
198
  //#endregion
228
199
  //#region src/hooks/useTheme.d.ts
229
200
  declare const useTheme: () => Theme;
230
- interface ThemeProviderProps<T$1 extends Theme> {
201
+ interface ThemeProviderProps<T extends Theme> {
231
202
  /**
232
203
  * The theme that should be used within the provider context.
233
204
  */
234
- theme: T$1;
205
+ theme: T;
235
206
  /**
236
207
  * The children of the component.
237
208
  */
@@ -241,11 +212,11 @@ interface ThemeProviderProps<T$1 extends Theme> {
241
212
  */
242
213
  className?: string;
243
214
  }
244
- declare function ThemeProvider<T$1 extends Theme>({
215
+ declare function ThemeProvider<T extends Theme>({
245
216
  theme,
246
217
  children,
247
218
  className
248
- }: ThemeProviderProps<T$1>): react0.JSX.Element;
219
+ }: ThemeProviderProps<T>): react_jsx_runtime0.JSX.Element;
249
220
  //#endregion
250
221
  //#region src/hooks/useSmallScreen.d.ts
251
222
  declare const useSmallScreen: () => boolean;
@@ -325,6 +296,76 @@ declare const defaultTheme: {
325
296
  components: {};
326
297
  };
327
298
  //#endregion
299
+ //#region src/utils/css-variables.utils.d.ts
300
+ /**
301
+ * Checks if the provided string represents a numeric scale value.
302
+ *
303
+ * A scale value is defined as a string containing only digits,
304
+ * optionally followed by a decimal point and more digits (e.g., "1", "2.5").
305
+ *
306
+ * @param value - The string to test for scale format.
307
+ * @returns `true` if the string is a valid scale value, otherwise `false`.
308
+ */
309
+ declare const isScale: (value: string) => boolean;
310
+ /**
311
+ * Represents the numeric values found in the default Tailwind CSS spacing scale.
312
+ *
313
+ * Includes:
314
+ * - Fractional steps: 0.5, 1.5, 2.5, 3.5
315
+ * - Integer steps: 0–12
316
+ * - Extended spacing steps: 14, 16, 20... up to 96
317
+ */
318
+ type ScaleValue = 0 | 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 3.5 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 72 | 80 | 96;
319
+ /**
320
+ * A strictly typed union of valid Tailwind CSS spacing keys.
321
+ * Accepts both the raw numbers (e.g., `4`, `2.5`) and their string equivalents (e.g., `"4"`, `"2.5"`).
322
+ *
323
+ * @example
324
+ * const spacing: Scale = 4; // Valid (matches w-4)
325
+ * const padding: Scale = "2.5"; // Valid (matches p-2.5)
326
+ */
327
+ type Scale = ScaleValue | `${ScaleValue}`;
328
+ /**
329
+ * Checks if a given string is a valid CSS custom property name (without the leading `--`).
330
+ *
331
+ * This simplified check ensures:
332
+ * - The name does not start with a digit.
333
+ * - It contains only word characters (letters, digits, underscore) or hyphens.
334
+ * - It must include at least one hyphen to be considered a custom property name.
335
+ */
336
+ declare const isValidCssCustomPropertyName: (val: string) => boolean;
337
+ /**
338
+ * Ensures that the given value is formatted as a CSS variable reference.
339
+ *
340
+ * If the provided value (`val`) is a valid CSS custom property name (without the leading `--`),
341
+ * the function returns a string in the form of `var(--<prefix-if-provided><val>, <val>)`. When a
342
+ * `prefix` is provided, it is prepended to the custom property name with a hyphen.
343
+ *
344
+ * If the value is not a valid custom property name, the function returns the original value.
345
+ */
346
+ declare const ensureCssVar: (val: string, prefix?: string) => string;
347
+ /**
348
+ * Creates a CSS custom properties object from the given key-value pairs.
349
+ *
350
+ * @param o - An object with string keys and string/number/undefined values
351
+ * @returns A CSSProperties object with `--` prefixed keys
352
+ */
353
+ declare const createVar: (o: {
354
+ [key: string]: string | number | undefined;
355
+ }) => CSSProperties;
356
+ /**
357
+ * Generates a CSS custom property for spacing that uses either a calc expression or a
358
+ * spacing variable reference.
359
+ *
360
+ * If `value` is a number (integer or decimal), uses the `--spacing` scale from Tailwind with calc().
361
+ * Otherwise, references a specific spacing variable (e.g., `--spacing-group`).
362
+ *
363
+ * @param name - The custom property name for spacing.
364
+ * @param value - Spacing value as a string (number or scale key).
365
+ * @returns Object with the CSS custom property for spacing.
366
+ */
367
+ declare const createSpacingVar: (name: string, value: string) => CSSProperties;
368
+ //#endregion
328
369
  //#region src/style-props.d.ts
329
370
  declare const width: {
330
371
  readonly auto: "w-auto";
@@ -621,8 +662,8 @@ declare const gapSpace: {
621
662
  readonly 80: "gap-80";
622
663
  readonly 96: "gap-96";
623
664
  readonly section: "gap-[var(--spacing-section)]";
624
- readonly fieldY: "gap-[var(--spacing-field-Y)]";
625
- readonly fieldX: "gap-[var(--spacing-field-X)]";
665
+ readonly fieldY: "gap-[var(--spacing-fieldY)]";
666
+ readonly fieldX: "gap-[var(--spacing-fieldX)]";
626
667
  readonly container: "gap-[var(--spacing-container)]";
627
668
  readonly group: "gap-[var(--spacing-group)]";
628
669
  };
@@ -889,6 +930,7 @@ declare const alignment: {
889
930
  readonly left: "items-start";
890
931
  readonly center: "items-center";
891
932
  readonly right: "items-end";
933
+ readonly stretch: "items-stretch";
892
934
  };
893
935
  readonly alignmentY: {
894
936
  readonly top: "justify-start";
@@ -1091,5 +1133,26 @@ type HeightProp = {
1091
1133
  */
1092
1134
  height?: keyof typeof height;
1093
1135
  };
1136
+ /**
1137
+ * Defines spacing properties for managing space between child elements.
1138
+ * @template T - A string type parameter that allows extending the base spacing
1139
+ * scale with custom values. Defaults to an empty string.
1140
+ */
1141
+ type SpaceProp<T extends string = ''> = {
1142
+ /**
1143
+ * Set the spacing between child elements.
1144
+ */
1145
+ space?: Scale | T;
1146
+ };
1147
+ //#endregion
1148
+ //#region src/utils/object.utils.d.ts
1149
+ /**
1150
+ * Safely get a dot-notated path within a nested object, with ability
1151
+ * to return a default if the full key path does not exist or
1152
+ * the value is undefined
1153
+ *
1154
+ * Based on: https://github.com/developit/dlv
1155
+ */
1156
+ declare const get: (obj: object, path: string, fallback?: any) => any;
1094
1157
  //#endregion
1095
- 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 FontSizeProp, type FontStyleProp, type FontWeightProp, type GapSpaceProp, type HeightProp, type MaxWidthProp, type NestedStringObject, type NumerFormatterOptions, NumericFormat, type PaddingBottomProp, type PaddingLeftProp, type PaddingRightProp, type PaddingSpaceProp, type PaddingSpacePropX, type PaddingSpacePropY, type PaddingTopProp, type PlaceItemsProp, type Props, SVG, type SVGProps, 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 WhiteSpaceProps, type WidthProp, alignment, aspect, cn, createVar, cursorStyle, cva, defaultTheme, ensureCssVar, extendTheme, fontWeight, gapSpace, get, height, isValidCssCustomPropertyName, maxWidth, paddingBottom, paddingLeft, paddingRight, paddingSpace, paddingSpaceX, paddingSpaceY, paddingTop, placeItems, textAlign, textSize, textStyle, textWrap, useClassNames, useResponsiveValue, useSmallScreen, useStateProps, useTheme, whiteSpace, width };
1158
+ 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 FontSizeProp, type FontStyleProp, type FontWeightProp, type GapSpaceProp, type HeightProp, type MaxWidthProp, type NestedStringObject, type NumerFormatterOptions, NumericFormat, 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 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 WhiteSpaceProps, type WidthProp, alignment, aspect, cn, createSpacingVar, createVar, cursorStyle, cva, defaultTheme, ensureCssVar, extendTheme, fontWeight, gapSpace, get, height, isScale, isValidCssCustomPropertyName, maxWidth, paddingBottom, paddingLeft, paddingRight, paddingSpace, paddingSpaceX, paddingSpaceY, paddingTop, placeItems, textAlign, textSize, textStyle, textWrap, useClassNames, useResponsiveValue, useSmallScreen, useStateProps, useTheme, whiteSpace, width };
package/dist/index.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as react0 from "react";
2
- import { Context, ReactNode } from "react";
2
+ import { CSSProperties, Context, ReactNode } from "react";
3
3
  import { VariantProps } from "class-variance-authority";
4
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
4
5
  import { DateFormatterOptions, useNumberFormatter } from "@react-aria/i18n";
5
6
  import { HtmlProps, KebabCase } from "@marigold/types";
6
7
  import { ClassProp, ClassValue, StringToBoolean } from "class-variance-authority/dist/types";
@@ -34,7 +35,7 @@ declare const DateFormat: ({
34
35
  value,
35
36
  tabular,
36
37
  ...props
37
- }: DateFormatProps) => react0.JSX.Element;
38
+ }: DateFormatProps) => react_jsx_runtime0.JSX.Element;
38
39
  //#endregion
39
40
  //#region src/components/Formatters/NumericFormat.d.ts
40
41
  type NumerFormatterOptions = NonNullable<Parameters<typeof useNumberFormatter>[0]>;
@@ -58,53 +59,23 @@ declare const NumericFormat: ({
58
59
  value,
59
60
  tabular,
60
61
  ...props
61
- }: NumericFormatProps) => react0.JSX.Element;
62
+ }: NumericFormatProps) => react_jsx_runtime0.JSX.Element;
62
63
  //#endregion
63
- //#region src/utils.d.ts
64
+ //#region src/utils/className.utils.d.ts
64
65
  type ConfigSchema = Record<string, Record<string, ClassValue>>;
65
- type ConfigVariants<T$1 extends ConfigSchema> = { [Variant in keyof T$1]?: StringToBoolean<keyof T$1[Variant]> | null | undefined };
66
- type ConfigVariantsMulti<T$1 extends ConfigSchema> = { [Variant in keyof T$1]?: StringToBoolean<keyof T$1[Variant]> | StringToBoolean<keyof T$1[Variant]>[] | undefined };
67
- type Config<T$1> = T$1 extends ConfigSchema ? {
68
- variants?: T$1;
69
- defaultVariants?: ConfigVariants<T$1>;
70
- compoundVariants?: (T$1 extends ConfigSchema ? (ConfigVariants<T$1> | ConfigVariantsMulti<T$1>) & ClassProp : ClassProp)[];
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)[];
71
72
  } : never;
72
- type Props<T$1> = T$1 extends ConfigSchema ? ConfigVariants<T$1> & ClassProp : ClassProp;
73
+ type Props<T> = T extends ConfigSchema ? ConfigVariants<T> & ClassProp : ClassProp;
73
74
  declare const cva: <T>(base?: ClassValue, config?: Config<T>) => {
74
75
  (props?: Props<T>): string;
75
76
  variants: T | undefined;
76
77
  };
77
78
  declare const cn: (...inputs: ClassValue[]) => string;
78
- declare const createVar: (o: {
79
- [key: string]: string | number | undefined;
80
- }) => React.CSSProperties;
81
- /**
82
- * Safely get a dot-notated path within a nested object, with ability
83
- * to return a default if the full key path does not exist or
84
- * the value is undefined
85
- *
86
- * Based on: https://github.com/developit/dlv
87
- */
88
- declare const get: (obj: object, path: string, fallback?: any) => any;
89
- /**
90
- * Checks if a given string is a valid CSS custom property name (without the leading `--`).
91
- *
92
- * This simplified check ensures:
93
- * - The name does not start with a digit.
94
- * - It contains only word characters (letters, digits, underscore) or hyphens.
95
- * - It must include at least one hyphen to be considered a custom property name.
96
- */
97
- declare const isValidCssCustomPropertyName: (val: string) => boolean;
98
- /**
99
- * Ensures that the given value is formatted as a CSS variable reference.
100
- *
101
- * If the provided value (`val`) is a valid CSS custom property name (without the leading `--`),
102
- * the function returns a string in the form of `var(--<prefix-if-provided><val>, <val>)`. When a
103
- * `prefix` is provided, it is prepended to the custom property name with a hyphen.
104
- *
105
- * If the value is not a valid custom property name, the function returns the original value.
106
- */
107
- declare const ensureCssVar: (val: string, prefix?: string) => string;
108
79
  //#endregion
109
80
  //#region src/types/theme.d.ts
110
81
  interface NestedStringObject {
@@ -180,8 +151,8 @@ type Theme = {
180
151
  };
181
152
  };
182
153
  type ComponentNames = keyof Theme['components'];
183
- type ThemeComponent<C$1 extends ComponentNames> = NonNullable<Theme['components'][C$1]>;
184
- type ThemeComponentParts<C$1 extends ComponentNames> = keyof ThemeComponent<C$1>;
154
+ type ThemeComponent<C extends ComponentNames> = NonNullable<Theme['components'][C]>;
155
+ type ThemeComponentParts<C extends ComponentNames> = keyof ThemeComponent<C>;
185
156
  //#endregion
186
157
  //#region src/hooks/useClassNames.d.ts
187
158
  interface ComponentContextProps {
@@ -189,14 +160,14 @@ interface ComponentContextProps {
189
160
  variant?: string;
190
161
  [key: string]: any;
191
162
  }
192
- interface UseClassNamesProps<C$1 extends ComponentNames> {
193
- component: C$1;
163
+ interface UseClassNamesProps<C extends ComponentNames> {
164
+ component: C;
194
165
  variant?: string;
195
166
  size?: string;
196
- className?: ThemeComponent<C$1> extends ((...args: any) => any) ? string : { [slot in keyof ThemeComponent<C$1>]?: string };
167
+ className?: ThemeComponent<C> extends ((...args: any) => any) ? string : { [slot in keyof ThemeComponent<C>]?: string };
197
168
  context?: Context<ComponentContextProps>;
198
169
  }
199
- type ComponentClassNames<C$1 extends ComponentNames> = ThemeComponent<C$1> extends ((...args: any) => any) ? string : { [slot in keyof ThemeComponent<C$1>]: string };
170
+ type ComponentClassNames<C extends ComponentNames> = ThemeComponent<C> extends ((...args: any) => any) ? string : { [slot in keyof ThemeComponent<C>]: string };
200
171
  declare const useClassNames: <C extends ComponentNames>({
201
172
  component,
202
173
  className,
@@ -227,11 +198,11 @@ declare const useStateProps: (states: UseStateProps) => StateAttrProps;
227
198
  //#endregion
228
199
  //#region src/hooks/useTheme.d.ts
229
200
  declare const useTheme: () => Theme;
230
- interface ThemeProviderProps<T$1 extends Theme> {
201
+ interface ThemeProviderProps<T extends Theme> {
231
202
  /**
232
203
  * The theme that should be used within the provider context.
233
204
  */
234
- theme: T$1;
205
+ theme: T;
235
206
  /**
236
207
  * The children of the component.
237
208
  */
@@ -241,11 +212,11 @@ interface ThemeProviderProps<T$1 extends Theme> {
241
212
  */
242
213
  className?: string;
243
214
  }
244
- declare function ThemeProvider<T$1 extends Theme>({
215
+ declare function ThemeProvider<T extends Theme>({
245
216
  theme,
246
217
  children,
247
218
  className
248
- }: ThemeProviderProps<T$1>): react0.JSX.Element;
219
+ }: ThemeProviderProps<T>): react_jsx_runtime0.JSX.Element;
249
220
  //#endregion
250
221
  //#region src/hooks/useSmallScreen.d.ts
251
222
  declare const useSmallScreen: () => boolean;
@@ -325,6 +296,76 @@ declare const defaultTheme: {
325
296
  components: {};
326
297
  };
327
298
  //#endregion
299
+ //#region src/utils/css-variables.utils.d.ts
300
+ /**
301
+ * Checks if the provided string represents a numeric scale value.
302
+ *
303
+ * A scale value is defined as a string containing only digits,
304
+ * optionally followed by a decimal point and more digits (e.g., "1", "2.5").
305
+ *
306
+ * @param value - The string to test for scale format.
307
+ * @returns `true` if the string is a valid scale value, otherwise `false`.
308
+ */
309
+ declare const isScale: (value: string) => boolean;
310
+ /**
311
+ * Represents the numeric values found in the default Tailwind CSS spacing scale.
312
+ *
313
+ * Includes:
314
+ * - Fractional steps: 0.5, 1.5, 2.5, 3.5
315
+ * - Integer steps: 0–12
316
+ * - Extended spacing steps: 14, 16, 20... up to 96
317
+ */
318
+ type ScaleValue = 0 | 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 3.5 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 72 | 80 | 96;
319
+ /**
320
+ * A strictly typed union of valid Tailwind CSS spacing keys.
321
+ * Accepts both the raw numbers (e.g., `4`, `2.5`) and their string equivalents (e.g., `"4"`, `"2.5"`).
322
+ *
323
+ * @example
324
+ * const spacing: Scale = 4; // Valid (matches w-4)
325
+ * const padding: Scale = "2.5"; // Valid (matches p-2.5)
326
+ */
327
+ type Scale = ScaleValue | `${ScaleValue}`;
328
+ /**
329
+ * Checks if a given string is a valid CSS custom property name (without the leading `--`).
330
+ *
331
+ * This simplified check ensures:
332
+ * - The name does not start with a digit.
333
+ * - It contains only word characters (letters, digits, underscore) or hyphens.
334
+ * - It must include at least one hyphen to be considered a custom property name.
335
+ */
336
+ declare const isValidCssCustomPropertyName: (val: string) => boolean;
337
+ /**
338
+ * Ensures that the given value is formatted as a CSS variable reference.
339
+ *
340
+ * If the provided value (`val`) is a valid CSS custom property name (without the leading `--`),
341
+ * the function returns a string in the form of `var(--<prefix-if-provided><val>, <val>)`. When a
342
+ * `prefix` is provided, it is prepended to the custom property name with a hyphen.
343
+ *
344
+ * If the value is not a valid custom property name, the function returns the original value.
345
+ */
346
+ declare const ensureCssVar: (val: string, prefix?: string) => string;
347
+ /**
348
+ * Creates a CSS custom properties object from the given key-value pairs.
349
+ *
350
+ * @param o - An object with string keys and string/number/undefined values
351
+ * @returns A CSSProperties object with `--` prefixed keys
352
+ */
353
+ declare const createVar: (o: {
354
+ [key: string]: string | number | undefined;
355
+ }) => CSSProperties;
356
+ /**
357
+ * Generates a CSS custom property for spacing that uses either a calc expression or a
358
+ * spacing variable reference.
359
+ *
360
+ * If `value` is a number (integer or decimal), uses the `--spacing` scale from Tailwind with calc().
361
+ * Otherwise, references a specific spacing variable (e.g., `--spacing-group`).
362
+ *
363
+ * @param name - The custom property name for spacing.
364
+ * @param value - Spacing value as a string (number or scale key).
365
+ * @returns Object with the CSS custom property for spacing.
366
+ */
367
+ declare const createSpacingVar: (name: string, value: string) => CSSProperties;
368
+ //#endregion
328
369
  //#region src/style-props.d.ts
329
370
  declare const width: {
330
371
  readonly auto: "w-auto";
@@ -621,8 +662,8 @@ declare const gapSpace: {
621
662
  readonly 80: "gap-80";
622
663
  readonly 96: "gap-96";
623
664
  readonly section: "gap-[var(--spacing-section)]";
624
- readonly fieldY: "gap-[var(--spacing-field-Y)]";
625
- readonly fieldX: "gap-[var(--spacing-field-X)]";
665
+ readonly fieldY: "gap-[var(--spacing-fieldY)]";
666
+ readonly fieldX: "gap-[var(--spacing-fieldX)]";
626
667
  readonly container: "gap-[var(--spacing-container)]";
627
668
  readonly group: "gap-[var(--spacing-group)]";
628
669
  };
@@ -889,6 +930,7 @@ declare const alignment: {
889
930
  readonly left: "items-start";
890
931
  readonly center: "items-center";
891
932
  readonly right: "items-end";
933
+ readonly stretch: "items-stretch";
892
934
  };
893
935
  readonly alignmentY: {
894
936
  readonly top: "justify-start";
@@ -1091,5 +1133,26 @@ type HeightProp = {
1091
1133
  */
1092
1134
  height?: keyof typeof height;
1093
1135
  };
1136
+ /**
1137
+ * Defines spacing properties for managing space between child elements.
1138
+ * @template T - A string type parameter that allows extending the base spacing
1139
+ * scale with custom values. Defaults to an empty string.
1140
+ */
1141
+ type SpaceProp<T extends string = ''> = {
1142
+ /**
1143
+ * Set the spacing between child elements.
1144
+ */
1145
+ space?: Scale | T;
1146
+ };
1147
+ //#endregion
1148
+ //#region src/utils/object.utils.d.ts
1149
+ /**
1150
+ * Safely get a dot-notated path within a nested object, with ability
1151
+ * to return a default if the full key path does not exist or
1152
+ * the value is undefined
1153
+ *
1154
+ * Based on: https://github.com/developit/dlv
1155
+ */
1156
+ declare const get: (obj: object, path: string, fallback?: any) => any;
1094
1157
  //#endregion
1095
- 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 FontSizeProp, type FontStyleProp, type FontWeightProp, type GapSpaceProp, type HeightProp, type MaxWidthProp, type NestedStringObject, type NumerFormatterOptions, NumericFormat, type PaddingBottomProp, type PaddingLeftProp, type PaddingRightProp, type PaddingSpaceProp, type PaddingSpacePropX, type PaddingSpacePropY, type PaddingTopProp, type PlaceItemsProp, type Props, SVG, type SVGProps, 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 WhiteSpaceProps, type WidthProp, alignment, aspect, cn, createVar, cursorStyle, cva, defaultTheme, ensureCssVar, extendTheme, fontWeight, gapSpace, get, height, isValidCssCustomPropertyName, maxWidth, paddingBottom, paddingLeft, paddingRight, paddingSpace, paddingSpaceX, paddingSpaceY, paddingTop, placeItems, textAlign, textSize, textStyle, textWrap, useClassNames, useResponsiveValue, useSmallScreen, useStateProps, useTheme, whiteSpace, width };
1158
+ 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 FontSizeProp, type FontStyleProp, type FontWeightProp, type GapSpaceProp, type HeightProp, type MaxWidthProp, type NestedStringObject, type NumerFormatterOptions, NumericFormat, 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 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 WhiteSpaceProps, type WidthProp, alignment, aspect, cn, createSpacingVar, createVar, cursorStyle, cva, defaultTheme, ensureCssVar, extendTheme, fontWeight, gapSpace, get, height, isScale, isValidCssCustomPropertyName, maxWidth, paddingBottom, paddingLeft, paddingRight, paddingSpace, paddingSpaceX, paddingSpaceY, paddingTop, placeItems, textAlign, textSize, textStyle, textWrap, useClassNames, useResponsiveValue, useSmallScreen, useStateProps, useTheme, whiteSpace, width };
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
- import { createContext, forwardRef, useCallback, useContext, useEffect, useRef, useState } from "react";
1
+ import { createContext, forwardRef, useCallback, useContext, useEffect, useMemo, useState } from "react";
2
2
  import { cva as cva$1, cx } from "class-variance-authority";
3
3
  import { twMerge } from "tailwind-merge";
4
+ import { jsx } from "react/jsx-runtime";
4
5
  import { useDateFormatter, useNumberFormatter } from "@react-aria/i18n";
5
- import isEqual from "react-fast-compare";
6
6
 
7
- //#region src/utils.ts
7
+ //#region src/utils/className.utils.ts
8
8
  const cva = (base, config) => {
9
9
  function styles(props) {
10
10
  return twMerge(cva$1(base, config)(props));
@@ -13,23 +13,19 @@ const cva = (base, config) => {
13
13
  return styles;
14
14
  };
15
15
  const cn = (...inputs) => twMerge(cx(inputs));
16
- const createVar = (o) => Object.fromEntries(Object.entries(o).map(([name, val]) => [`--${name}`, val]));
16
+
17
+ //#endregion
18
+ //#region src/utils/css-variables.utils.ts
17
19
  /**
18
- * Safely get a dot-notated path within a nested object, with ability
19
- * to return a default if the full key path does not exist or
20
- * the value is undefined
20
+ * Checks if the provided string represents a numeric scale value.
21
21
  *
22
- * Based on: https://github.com/developit/dlv
22
+ * A scale value is defined as a string containing only digits,
23
+ * optionally followed by a decimal point and more digits (e.g., "1", "2.5").
24
+ *
25
+ * @param value - The string to test for scale format.
26
+ * @returns `true` if the string is a valid scale value, otherwise `false`.
23
27
  */
24
- const get = (obj, path, fallback) => {
25
- const key = path.split(".");
26
- let result = obj;
27
- for (let i = 0, length = key.length; i < length; i++) {
28
- if (!result) break;
29
- result = result[key[i]];
30
- }
31
- return result === void 0 ? fallback : result;
32
- };
28
+ const isScale = (value) => /^[0-9]+(\.[0-9]+)?$/.test(value);
33
29
  /**
34
30
  * Checks if a given string is a valid CSS custom property name (without the leading `--`).
35
31
  *
@@ -49,32 +45,60 @@ const isValidCssCustomPropertyName = (val) => /^[A-Za-z0-9_-]+$/.test(val);
49
45
  * If the value is not a valid custom property name, the function returns the original value.
50
46
  */
51
47
  const ensureCssVar = (val, prefix) => isValidCssCustomPropertyName(val) ? `var(--${prefix ? `${prefix}-` : ""}${val}, ${val})` : val;
48
+ /**
49
+ * Creates a CSS custom properties object from the given key-value pairs.
50
+ *
51
+ * @param o - An object with string keys and string/number/undefined values
52
+ * @returns A CSSProperties object with `--` prefixed keys
53
+ */
54
+ const createVar = (o) => Object.fromEntries(Object.entries(o).map(([name, val]) => [`--${name}`, val]));
55
+ /**
56
+ * Generates a CSS custom property for spacing that uses either a calc expression or a
57
+ * spacing variable reference.
58
+ *
59
+ * If `value` is a number (integer or decimal), uses the `--spacing` scale from Tailwind with calc().
60
+ * Otherwise, references a specific spacing variable (e.g., `--spacing-group`).
61
+ *
62
+ * @param name - The custom property name for spacing.
63
+ * @param value - Spacing value as a string (number or scale key).
64
+ * @returns Object with the CSS custom property for spacing.
65
+ */
66
+ const createSpacingVar = (name, value) => {
67
+ return { [`--${name}`]: isScale(value) ? `calc(var(--spacing) * ${value})` : `var(--spacing-${value})` };
68
+ };
52
69
 
53
70
  //#endregion
54
71
  //#region src/components/SVG/SVG.tsx
55
- const SVG = forwardRef(({ size = 24, children, className, color,...props }, ref) => {
56
- return /* @__PURE__ */ React.createElement("svg", {
72
+ const SVG = forwardRef(({ size = 24, children, className, color, ...props }, ref) => {
73
+ return /* @__PURE__ */ jsx("svg", {
57
74
  ...props,
58
75
  ref,
59
76
  width: `${props.width || size}px`,
60
77
  height: `${props.height || size}px`,
61
78
  className: cn("flex-none fill-current", className),
62
- style: { color: color && ensureCssVar(color, "color") }
63
- }, children);
79
+ style: { color: color && ensureCssVar(color, "color") },
80
+ children
81
+ });
64
82
  });
65
83
 
66
84
  //#endregion
67
85
  //#region src/components/Formatters/DateFormat.tsx
68
- const DateFormat = ({ value, tabular,...props }) => {
86
+ const DateFormat = ({ value, tabular, ...props }) => {
69
87
  const formatter = useDateFormatter({ ...props });
70
- return /* @__PURE__ */ React.createElement("span", { className: tabular ? "tabular-nums" : "" }, Array.isArray(value) ? formatter.formatRange(value[0], value[1]) : formatter.format(value));
88
+ return /* @__PURE__ */ jsx("span", {
89
+ className: tabular ? "tabular-nums" : "",
90
+ children: Array.isArray(value) ? formatter.formatRange(value[0], value[1]) : formatter.format(value)
91
+ });
71
92
  };
72
93
 
73
94
  //#endregion
74
95
  //#region src/components/Formatters/NumericFormat.tsx
75
- const NumericFormat = ({ value, tabular = true,...props }) => {
96
+ const NumericFormat = ({ value, tabular = true, ...props }) => {
76
97
  const formatter = useNumberFormatter({ ...props });
77
- return /* @__PURE__ */ React.createElement("span", { className: tabular ? "tabular-nums" : void 0 }, Array.isArray(value) ? formatter.formatRange(value[0], value[1]) : formatter.format(value));
98
+ return /* @__PURE__ */ jsx("span", {
99
+ className: tabular ? "tabular-nums" : void 0,
100
+ children: Array.isArray(value) ? formatter.formatRange(value[0], value[1]) : formatter.format(value)
101
+ });
78
102
  };
79
103
 
80
104
  //#endregion
@@ -98,7 +122,13 @@ const useTheme = () => {
98
122
  return useContext(InternalContext);
99
123
  };
100
124
  function ThemeProvider({ theme, children, className }) {
101
- return /* @__PURE__ */ React.createElement(InternalContext.Provider, { value: theme }, /* @__PURE__ */ React.createElement("div", { className }, children));
125
+ return /* @__PURE__ */ jsx(InternalContext.Provider, {
126
+ value: theme,
127
+ children: /* @__PURE__ */ jsx("div", {
128
+ className,
129
+ children
130
+ })
131
+ });
102
132
  }
103
133
 
104
134
  //#endregion
@@ -132,6 +162,14 @@ const useClassNames = ({ component, className, variant, size, context: Component
132
162
  //#endregion
133
163
  //#region src/hooks/useResponsiveValue.ts
134
164
  /**
165
+ * Based on https://theme-ui.com/packages/match-media/
166
+ */
167
+ /**
168
+ * Hardcode fallback breakpoints, not make sure `useEffect`
169
+ * doesn't trigger on every render. Since it is part of the
170
+ * dependency array.
171
+ */
172
+ /**
135
173
  * Hook that can be used to return values based on the current screen size,
136
174
  * using breakpoints from the theme (`theme.breakpoints`). Note that this
137
175
  * hook is client.side only.
@@ -167,14 +205,14 @@ const toKebap = (val) => val.replace(KEBAB_REGEX, (match) => `-${match.toLocaleL
167
205
  * (e.g. `[data-hover]` and `[data-focus]`).
168
206
  */
169
207
  const useStateProps = (states) => {
170
- const statePropsRef = useRef({});
171
- let stateProps = {};
172
- for (let state in states) if (states[state]) {
173
- const key = `data-${toKebap(state)}`;
174
- stateProps[key] = "";
175
- }
176
- if (!isEqual(statePropsRef.current, stateProps)) statePropsRef.current = stateProps;
177
- return statePropsRef.current;
208
+ return useMemo(() => {
209
+ const stateProps = {};
210
+ for (const state in states) if (states[state]) {
211
+ const key = `data-${toKebap(state)}`;
212
+ stateProps[key] = "";
213
+ }
214
+ return stateProps;
215
+ }, [states]);
178
216
  };
179
217
 
180
218
  //#endregion
@@ -184,12 +222,11 @@ const useSmallScreen = () => {
184
222
  if (typeof window == "undefined") return false;
185
223
  return window.matchMedia("(max-width: 600px)").matches;
186
224
  };
187
- const [matches, setMatches] = useState(getMatches());
225
+ const [matches, setMatches] = useState(getMatches);
188
226
  const handleResize = useCallback(() => {
189
227
  setMatches(getMatches());
190
228
  }, []);
191
229
  useEffect(() => {
192
- handleResize();
193
230
  if (typeof window == "undefined") return;
194
231
  window.addEventListener("resize", handleResize);
195
232
  return () => window.removeEventListener("resize", handleResize);
@@ -538,8 +575,8 @@ const gapSpace = {
538
575
  80: "gap-80",
539
576
  96: "gap-96",
540
577
  section: "gap-[var(--spacing-section)]",
541
- fieldY: "gap-[var(--spacing-field-Y)]",
542
- fieldX: "gap-[var(--spacing-field-X)]",
578
+ fieldY: "gap-[var(--spacing-fieldY)]",
579
+ fieldX: "gap-[var(--spacing-fieldX)]",
543
580
  container: "gap-[var(--spacing-container)]",
544
581
  group: "gap-[var(--spacing-group)]"
545
582
  };
@@ -805,7 +842,8 @@ const alignment = {
805
842
  alignmentX: {
806
843
  left: "items-start",
807
844
  center: "items-center",
808
- right: "items-end"
845
+ right: "items-end",
846
+ stretch: "items-stretch"
809
847
  },
810
848
  alignmentY: {
811
849
  top: "justify-start",
@@ -881,4 +919,23 @@ const cursorStyle = {
881
919
  };
882
920
 
883
921
  //#endregion
884
- export { DateFormat, NumericFormat, SVG, ThemeProvider, alignment, aspect, cn, createVar, cursorStyle, cva, defaultTheme, ensureCssVar, extendTheme, fontWeight, gapSpace, get, height, isValidCssCustomPropertyName, maxWidth, paddingBottom, paddingLeft, paddingRight, paddingSpace, paddingSpaceX, paddingSpaceY, paddingTop, placeItems, textAlign, textSize, textStyle, textWrap, useClassNames, useResponsiveValue, useSmallScreen, useStateProps, useTheme, whiteSpace, width };
922
+ //#region src/utils/object.utils.ts
923
+ /**
924
+ * Safely get a dot-notated path within a nested object, with ability
925
+ * to return a default if the full key path does not exist or
926
+ * the value is undefined
927
+ *
928
+ * Based on: https://github.com/developit/dlv
929
+ */
930
+ const get = (obj, path, fallback) => {
931
+ const key = path.split(".");
932
+ let result = obj;
933
+ for (let i = 0, length = key.length; i < length; i++) {
934
+ if (!result) break;
935
+ result = result[key[i]];
936
+ }
937
+ return result === void 0 ? fallback : result;
938
+ };
939
+
940
+ //#endregion
941
+ export { DateFormat, NumericFormat, SVG, ThemeProvider, alignment, aspect, cn, createSpacingVar, createVar, cursorStyle, cva, defaultTheme, ensureCssVar, extendTheme, fontWeight, gapSpace, get, height, isScale, isValidCssCustomPropertyName, maxWidth, paddingBottom, paddingLeft, paddingRight, paddingSpace, paddingSpaceX, paddingSpaceY, paddingTop, placeItems, textAlign, textSize, textStyle, textWrap, useClassNames, useResponsiveValue, useSmallScreen, useStateProps, useTheme, whiteSpace, width };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marigold/system",
3
- "version": "16.0.0",
3
+ "version": "16.1.0",
4
4
  "description": "Marigold System Library",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -51,8 +51,8 @@
51
51
  "postcss": "8.5.6",
52
52
  "react": "19.2.0",
53
53
  "tailwindcss": "4.1.17",
54
- "tsdown": "0.15.9",
55
- "@marigold/tsconfig": "0.4.1"
54
+ "tsdown": "0.16.8",
55
+ "@marigold/tsconfig": "0.4.2"
56
56
  },
57
57
  "scripts": {
58
58
  "build": "tsdown src/index.ts",