@mond-design-system/react 2.0.0 → 3.0.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.d.ts CHANGED
@@ -83,8 +83,11 @@ interface SpinnerProps extends HTMLAttributes<HTMLSpanElement> {
83
83
  declare function Spinner({ size, label, className, style, ...rest }: SpinnerProps): ReactElement;
84
84
 
85
85
  interface IconRenderProps {
86
- /** Pixel size of the requested step. */
87
- size: number;
86
+ /** Pixel size of the requested step, or undefined when the glyph should take
87
+ the size of the slot it sits in. An icon set that can only be sized with a
88
+ number falls back to its own default; one that can read a CSS length uses
89
+ var(--mds-icon-slot, var(--mds-icon-md)). */
90
+ size?: number | undefined;
88
91
  }
89
92
  /** Brand-owned glyph resolver: name → rendered glyph (svg, font ligature, …). */
90
93
  type IconRender = (name: string, props: IconRenderProps) => ReactNode;
@@ -99,7 +102,7 @@ interface IconProviderProps {
99
102
  *
100
103
  * ```tsx
101
104
  * // App root: map names to your icon set once.
102
- * <IconProvider render={(name, { size }) => <MyGlyph name={name} width={size} />}>
105
+ * <IconProvider render={(name, { size }) => <MyGlyph name={name} width={size ?? 20} />}>
103
106
  * <App />
104
107
  * </IconProvider>
105
108
  *
@@ -112,7 +115,8 @@ type IconSize = "sm" | "md" | "lg";
112
115
  interface IconProps extends HTMLAttributes<HTMLSpanElement> {
113
116
  /** Glyph name in the app's registered set. */
114
117
  name: string;
115
- /** Default "md". */
118
+ /** A step on the icon scale. Left unset, the glyph takes the step of the
119
+ control slot around it, and the md step outside one. */
116
120
  size?: IconSize;
117
121
  /** Accessible name. Omitted = decorative (aria-hidden). */
118
122
  label?: string;
@@ -332,7 +336,8 @@ declare function ChipBar({ children, gap, bordered, fade, className, ...rest }:
332
336
 
333
337
  type CountButtonTone = "accent" | "danger";
334
338
  interface CountButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "aria-label" | "aria-pressed"> {
335
- /** Glyph shown before the text, e.g. `<Icon name="heart" />` (md). */
339
+ /** Glyph shown before the text, e.g. `<Icon name="heart" />`. Sized by the
340
+ button, whatever the icon set's own default is. */
336
341
  icon: ReactNode;
337
342
  /** Accessible label (required) — describes the action for screen readers. */
338
343
  label: string;
@@ -553,7 +558,7 @@ interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size">
553
558
  * <Input value={name} onChange={(e) => setName(e.target.value)} />
554
559
  * </Field>
555
560
  *
556
- * <Input aria-label="Search" iconLeft={<Icon name="search" size="sm" />} />
561
+ * <Input aria-label="Search" iconLeft={<Icon name="search" />} />
557
562
  * ```
558
563
  */
559
564
  declare function Input({ size, invalid, iconLeft, iconRight, className, ...rest }: InputProps): ReactElement;
@@ -1268,12 +1273,14 @@ declare const OverlayHistoryContext: react.Context<OverlayHistory | null>;
1268
1273
  interface Presence {
1269
1274
  /** Keep the element in the DOM (true during exit animation). */
1270
1275
  mounted: boolean;
1271
- /** Drive the visual state — false during exit. */
1276
+ /** Drive the visual state — false on the frame it enters and during exit. */
1272
1277
  visible: boolean;
1273
1278
  }
1274
1279
  /**
1275
- * Exit-animation helper. `open` flips instantly; `mounted` lags by
1276
- * `durationMs` on close so the exit transition can play.
1280
+ * Enter/exit animation helper. An element inserted already carrying its open
1281
+ * style has nothing to transition from, so `visible` stays false for the frame
1282
+ * the closed style is painted in and flips on the next one. `mounted` lags
1283
+ * `open` by `durationMs` on close so the exit transition can finish.
1277
1284
  */
1278
1285
  declare function usePresence(open: boolean, durationMs: number): Presence;
1279
1286
 
package/dist/index.js CHANGED
@@ -101,14 +101,14 @@ function Spinner({
101
101
  }
102
102
 
103
103
  // mds-cssmod:/home/runner/work/mond-design-system/mond-design-system/packages/react/src/components/Icon/Icon.module.css?mds-scoped
104
- var Icon_module_default = { "icon": "mds-Icon__icon", "size-sm": "mds-Icon__size-sm", "size-md": "mds-Icon__size-md", "size-lg": "mds-Icon__size-lg" };
104
+ var Icon_module_default = { "icon": "mds-Icon__icon", "size-slot": "mds-Icon__size-slot", "size-sm": "mds-Icon__size-sm", "size-md": "mds-Icon__size-md", "size-lg": "mds-Icon__size-lg" };
105
105
  var IconContext = createContext(null);
106
106
  function IconProvider({ render, children }) {
107
107
  return /* @__PURE__ */ jsx(IconContext.Provider, { value: render, children });
108
108
  }
109
109
  var SIZE_PX = { sm: 16, md: 20, lg: 24 };
110
110
  var warned = /* @__PURE__ */ new Set();
111
- function Icon({ name, size = "md", label, className, ...rest }) {
111
+ function Icon({ name, size, label, className, ...rest }) {
112
112
  const render = useContext(IconContext);
113
113
  if (render === null && !warned.has(name)) {
114
114
  warned.add(name);
@@ -119,10 +119,10 @@ function Icon({ name, size = "md", label, className, ...rest }) {
119
119
  return /* @__PURE__ */ jsx(
120
120
  "span",
121
121
  {
122
- className: cx(Icon_module_default.icon, Icon_module_default[`size-${size}`], className),
122
+ className: cx(Icon_module_default.icon, Icon_module_default[`size-${size ?? "slot"}`], className),
123
123
  ...label ? { role: "img", "aria-label": label } : { "aria-hidden": true },
124
124
  ...rest,
125
- children: render?.(name, { size: SIZE_PX[size] })
125
+ children: render?.(name, { size: size === void 0 ? void 0 : SIZE_PX[size] })
126
126
  }
127
127
  );
128
128
  }
@@ -369,7 +369,7 @@ function CountButton({
369
369
  className: cx(CountButton_module_default.button, active && CountButton_module_default[`tone-${tone}`], className),
370
370
  ...rest,
371
371
  children: [
372
- loading ? /* @__PURE__ */ jsx(Spinner, { size: SPINNER_PX, label: "", "aria-hidden": "true" }) : /* @__PURE__ */ jsx("span", { className: CountButton_module_default.glyph, children: icon }),
372
+ /* @__PURE__ */ jsx("span", { className: CountButton_module_default.glyph, children: loading ? /* @__PURE__ */ jsx(Spinner, { size: SPINNER_PX, label: "", "aria-hidden": "true" }) : icon }),
373
373
  children != null ? /* @__PURE__ */ jsx("span", { children }) : null
374
374
  ]
375
375
  }
@@ -479,20 +479,34 @@ function useOverlay(options) {
479
479
  }
480
480
  function usePresence(open, durationMs) {
481
481
  const [mounted, setMounted] = useState(open);
482
+ const [visible, setVisible] = useState(false);
482
483
  if (open && !mounted) setMounted(true);
484
+ if (!open && visible) setVisible(false);
485
+ useEffect(() => {
486
+ if (!open) return;
487
+ let second = 0;
488
+ const first = requestAnimationFrame(() => {
489
+ second = requestAnimationFrame(() => setVisible(true));
490
+ });
491
+ return () => {
492
+ cancelAnimationFrame(first);
493
+ cancelAnimationFrame(second);
494
+ };
495
+ }, [open]);
483
496
  useEffect(() => {
484
497
  if (open) return;
485
498
  const timer = setTimeout(() => setMounted(false), durationMs);
486
499
  return () => clearTimeout(timer);
487
500
  }, [open, durationMs]);
488
- return { mounted: open || mounted, visible: open };
501
+ return { mounted: open || mounted, visible };
489
502
  }
490
503
 
491
504
  // mds-cssmod:/home/runner/work/mond-design-system/mond-design-system/packages/react/src/components/Overlay/Overlay.module.css?mds-scoped
492
505
  var Overlay_module_default = { "scrim": "mds-Overlay__scrim", "variant-modal": "mds-Overlay__variant-modal", "variant-sheet": "mds-Overlay__variant-sheet" };
493
506
  var OVERLAY_EXIT_MS = 200;
507
+ var SHEET_EXIT_MS = 320;
494
508
  function Overlay({ open, onClose, label, variant, role = "dialog", closeOnScrimClick, panelClassName, children }) {
495
- const { mounted, visible } = usePresence(open, OVERLAY_EXIT_MS);
509
+ const { mounted, visible } = usePresence(open, variant === "sheet" ? SHEET_EXIT_MS : OVERLAY_EXIT_MS);
496
510
  const ref = useOverlay({ open, onClose });
497
511
  if (!mounted) return null;
498
512
  return createPortal(