@salemcobalt/ui 0.2.0-rc.33 → 0.2.0-rc.35

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
@@ -1908,7 +1908,7 @@ interface ToastProviderProps {
1908
1908
  * Provider inside another adds nothing (its `timeout` and `limit` are ignored), so a component may wrap itself in one
1909
1909
  * and still share the app's.
1910
1910
  */
1911
- declare function Provider({ children, timeout, limit }: ToastProviderProps): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | react.JSX.Element | null | undefined;
1911
+ declare function Provider({ children, timeout, limit }: ToastProviderProps): string | number | bigint | boolean | react.JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | null | undefined;
1912
1912
  interface ToastApi {
1913
1913
  /** Shows a toast and returns its id. */
1914
1914
  add: (options: ToastOptions) => string;
package/dist/index.js CHANGED
@@ -237,7 +237,7 @@ function attachSheetSwipe(handle) {
237
237
  return;
238
238
  }
239
239
  dragging = true;
240
- height = popup.getBoundingClientRect().height;
240
+ height = popup.getBoundingClientRect().height - (parseFloat(getComputedStyle(popup).borderBottomWidth) || 0);
241
241
  popup.dataset.swiping = "";
242
242
  popup.setPointerCapture?.(e.pointerId);
243
243
  window.getSelection()?.removeAllRanges();
@@ -270,10 +270,14 @@ function attachSheetSwipe(handle) {
270
270
  };
271
271
  if (shouldDismissSheet(release)) {
272
272
  delete popup.dataset.swiping;
273
+ popup.dataset.swiped = "";
273
274
  handle.click();
274
275
  suppressClick = true;
275
276
  window.requestAnimationFrame(() => {
276
- if (popup.isConnected && popup.hasAttribute("data-open")) settle();
277
+ if (popup.isConnected && popup.hasAttribute("data-open")) {
278
+ delete popup.dataset.swiped;
279
+ settle();
280
+ }
277
281
  });
278
282
  } else {
279
283
  suppressClick = true;
@@ -634,7 +638,7 @@ function Content({
634
638
  const isSheet = variant === "sheet";
635
639
  const swipe = isSheet && dismissOnSwipe && dismissible;
636
640
  return /* @__PURE__ */ jsxs5(BaseDialog.Portal, { children: [
637
- /* @__PURE__ */ jsx6(BaseDialog.Backdrop, { className: "sc-dialog__backdrop", forceRender: true }),
641
+ /* @__PURE__ */ jsx6(BaseDialog.Backdrop, { className: "sc-dialog__backdrop", "data-variant": variant, forceRender: true }),
638
642
  /* @__PURE__ */ jsxs5(
639
643
  BaseDialog.Popup,
640
644
  {
@@ -739,6 +743,51 @@ import { useRender as useRender2 } from "@base-ui/react/use-render";
739
743
 
740
744
  // src/components/Tooltip/Tooltip.tsx
741
745
  import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
746
+
747
+ // src/utils/useSafeAreaPadding.ts
748
+ import { useSyncExternalStore } from "react";
749
+ var EDGE = 5;
750
+ var NONE = { top: EDGE, right: EDGE, bottom: EDGE, left: EDGE };
751
+ var current = NONE;
752
+ var listeners = /* @__PURE__ */ new Set();
753
+ function measure() {
754
+ const probe = document.createElement("div");
755
+ probe.setAttribute("data-sc-safe-area-probe", "");
756
+ probe.style.cssText = "position:fixed;visibility:hidden;pointer-events:none;padding:env(safe-area-inset-top,0px) env(safe-area-inset-right,0px) env(safe-area-inset-bottom,0px) env(safe-area-inset-left,0px)";
757
+ document.body.appendChild(probe);
758
+ const style = getComputedStyle(probe);
759
+ const px = (value) => EDGE + (parseFloat(value) || 0);
760
+ const next = {
761
+ top: px(style.paddingTop),
762
+ right: px(style.paddingRight),
763
+ bottom: px(style.paddingBottom),
764
+ left: px(style.paddingLeft)
765
+ };
766
+ probe.remove();
767
+ if (next.top === current.top && next.right === current.right && next.bottom === current.bottom && next.left === current.left) {
768
+ return;
769
+ }
770
+ current = next;
771
+ listeners.forEach((listener) => listener());
772
+ }
773
+ function subscribe(onChange) {
774
+ if (listeners.size === 0) window.addEventListener("resize", measure);
775
+ listeners.add(onChange);
776
+ measure();
777
+ return () => {
778
+ listeners.delete(onChange);
779
+ if (listeners.size === 0) window.removeEventListener("resize", measure);
780
+ };
781
+ }
782
+ function useSafeAreaPadding() {
783
+ return useSyncExternalStore(
784
+ subscribe,
785
+ () => current,
786
+ () => NONE
787
+ );
788
+ }
789
+
790
+ // src/components/Tooltip/Tooltip.tsx
742
791
  import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
743
792
  function TooltipBase({
744
793
  content,
@@ -753,6 +802,7 @@ function TooltipBase({
753
802
  disabled,
754
803
  className
755
804
  }) {
805
+ const collisionPadding = useSafeAreaPadding();
756
806
  return /* @__PURE__ */ jsxs6(
757
807
  BaseTooltip.Root,
758
808
  {
@@ -762,10 +812,20 @@ function TooltipBase({
762
812
  disabled,
763
813
  children: [
764
814
  /* @__PURE__ */ jsx7(BaseTooltip.Trigger, { render: children, delay, closeDelay }),
765
- /* @__PURE__ */ jsx7(BaseTooltip.Portal, { children: /* @__PURE__ */ jsx7(BaseTooltip.Positioner, { side, align, sideOffset: 6, className: "sc-tooltip__positioner", children: /* @__PURE__ */ jsxs6(BaseTooltip.Popup, { role: "tooltip", className: cx("sc-tooltip", className), children: [
766
- /* @__PURE__ */ jsx7(BaseTooltip.Arrow, { className: "sc-tooltip__arrow" }),
767
- content
768
- ] }) }) })
815
+ /* @__PURE__ */ jsx7(BaseTooltip.Portal, { children: /* @__PURE__ */ jsx7(
816
+ BaseTooltip.Positioner,
817
+ {
818
+ side,
819
+ align,
820
+ sideOffset: 6,
821
+ collisionPadding,
822
+ className: "sc-tooltip__positioner",
823
+ children: /* @__PURE__ */ jsxs6(BaseTooltip.Popup, { role: "tooltip", className: cx("sc-tooltip", className), children: [
824
+ /* @__PURE__ */ jsx7(BaseTooltip.Arrow, { className: "sc-tooltip__arrow" }),
825
+ content
826
+ ] })
827
+ }
828
+ ) })
769
829
  ]
770
830
  }
771
831
  );
@@ -862,7 +922,18 @@ function Content2({
862
922
  children,
863
923
  ...rest
864
924
  }) {
865
- return /* @__PURE__ */ jsx9(BaseMenu.Portal, { children: /* @__PURE__ */ jsx9(BaseMenu.Positioner, { side, align, sideOffset, className: "sc-menu__positioner", children: /* @__PURE__ */ jsx9(BaseMenu.Popup, { className: cx("sc-menu", className), ...rest, children }) }) });
925
+ const collisionPadding = useSafeAreaPadding();
926
+ return /* @__PURE__ */ jsx9(BaseMenu.Portal, { children: /* @__PURE__ */ jsx9(
927
+ BaseMenu.Positioner,
928
+ {
929
+ side,
930
+ align,
931
+ sideOffset,
932
+ collisionPadding,
933
+ className: "sc-menu__positioner",
934
+ children: /* @__PURE__ */ jsx9(BaseMenu.Popup, { className: cx("sc-menu", className), ...rest, children })
935
+ }
936
+ ) });
866
937
  }
867
938
  function useItemBody({
868
939
  icon,
@@ -1191,12 +1262,13 @@ function Select({
1191
1262
  const items = options.flatMap((entry) => isGroup(entry) ? entry.options : [entry]);
1192
1263
  const [internal, setInternal] = useState(defaultValue ?? null);
1193
1264
  const controlled = value !== void 0;
1194
- const current = controlled ? value : internal;
1265
+ const current2 = controlled ? value : internal;
1195
1266
  const setValue = (next) => {
1196
1267
  if (!controlled) setInternal(next);
1197
1268
  onValueChange?.(next);
1198
1269
  };
1199
- const canClear = clearable && current != null && !disabled && !readOnly;
1270
+ const canClear = clearable && current2 != null && !disabled && !readOnly;
1271
+ const collisionPadding = useSafeAreaPadding();
1200
1272
  const onTriggerKeyDown = (event) => {
1201
1273
  if (canClear && (event.key === "Backspace" || event.key === "Delete")) {
1202
1274
  event.preventDefault();
@@ -1220,7 +1292,7 @@ function Select({
1220
1292
  BaseSelect.Root,
1221
1293
  {
1222
1294
  items,
1223
- value: current,
1295
+ value: current2,
1224
1296
  onValueChange: (next) => setValue(next),
1225
1297
  disabled,
1226
1298
  required,
@@ -1258,6 +1330,7 @@ function Select({
1258
1330
  {
1259
1331
  className: "sc-select__positioner",
1260
1332
  sideOffset: 4,
1333
+ collisionPadding,
1261
1334
  alignItemWithTrigger: false,
1262
1335
  children: /* @__PURE__ */ jsx13(BaseSelect.Popup, { className: "sc-select__popup", children: /* @__PURE__ */ jsx13(BaseSelect.List, { children: options.map(
1263
1336
  (entry, i) => isGroup(entry) ? /* @__PURE__ */ jsxs11(BaseSelect.Group, { className: "sc-select__group", children: [
@@ -1529,12 +1602,12 @@ function Progress({
1529
1602
  className,
1530
1603
  ...rest
1531
1604
  }) {
1532
- const current = value ?? null;
1533
- const hasValueText = valueText != null || showValue && current !== null;
1605
+ const current2 = value ?? null;
1606
+ const hasValueText = valueText != null || showValue && current2 !== null;
1534
1607
  return /* @__PURE__ */ jsxs17(
1535
1608
  BaseProgress.Root,
1536
1609
  {
1537
- value: current,
1610
+ value: current2,
1538
1611
  max,
1539
1612
  min,
1540
1613
  getAriaValueText: (formatted) => typeof valueText === "string" ? valueText : formatted ?? "",
@@ -2474,9 +2547,9 @@ function fileTypeLabel(file) {
2474
2547
  }
2475
2548
 
2476
2549
  // src/utils/useMediaQuery.ts
2477
- import { useCallback as useCallback2, useSyncExternalStore } from "react";
2550
+ import { useCallback as useCallback2, useSyncExternalStore as useSyncExternalStore2 } from "react";
2478
2551
  function useMediaQuery(query) {
2479
- const subscribe = useCallback2(
2552
+ const subscribe2 = useCallback2(
2480
2553
  (onChange) => {
2481
2554
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return () => {
2482
2555
  };
@@ -2486,8 +2559,8 @@ function useMediaQuery(query) {
2486
2559
  },
2487
2560
  [query]
2488
2561
  );
2489
- return useSyncExternalStore(
2490
- subscribe,
2562
+ return useSyncExternalStore2(
2563
+ subscribe2,
2491
2564
  () => typeof window.matchMedia === "function" && window.matchMedia(query).matches,
2492
2565
  () => false
2493
2566
  );
@@ -2642,7 +2715,7 @@ function FileInput({
2642
2715
  const messagesId = `${id}messages`;
2643
2716
  const controlled = files !== void 0;
2644
2717
  const [uncontrolledFiles, setUncontrolledFiles] = useState6(defaultFiles ?? []);
2645
- const current = controlled ? files : uncontrolledFiles;
2718
+ const current2 = controlled ? files : uncontrolledFiles;
2646
2719
  const [rejections, setRejections] = useState6([]);
2647
2720
  const [inputId, setInputId] = useState6();
2648
2721
  const [previewFile, setPreviewFile] = useState6(null);
@@ -2654,21 +2727,21 @@ function FileInput({
2654
2727
  const moduleRef = useRef4(null);
2655
2728
  const patchRef = useRef4(() => {
2656
2729
  });
2657
- const settledRef = useRef4(current);
2730
+ const settledRef = useRef4(current2);
2658
2731
  const targetRef = useRef4(null);
2659
2732
  const acceptList = parseAccept(accept);
2660
2733
  const acceptAttr = acceptList.join(",");
2661
2734
  const maxBytes = parseSize(maxFileSize);
2662
2735
  const messages = [...rejections, ...error != null ? [error] : []];
2663
2736
  const isInvalid = invalid || messages.length > 0;
2664
- const idleText = idleLabel ?? (multiple ? "Drop files here or" : current.length > 0 ? "Drop another file to replace it, or" : "Drop a file here or");
2737
+ const idleText = idleLabel ?? (multiple ? "Drop files here or" : current2.length > 0 ? "Drop another file to replace it, or" : "Drop a file here or");
2665
2738
  const live = {
2666
2739
  acceptList,
2667
2740
  acceptLabel: acceptLabel ?? describeAccept(acceptList),
2668
2741
  maxBytes,
2669
2742
  maxFiles: multiple ? maxFiles : 1,
2670
2743
  multiple,
2671
- current,
2744
+ current: current2,
2672
2745
  controlled,
2673
2746
  onFilesChange,
2674
2747
  labelId,
@@ -2910,15 +2983,15 @@ function FileInput({
2910
2983
  const items = pond.getFiles();
2911
2984
  const idle = items.filter((item) => item.status === mod.FileStatus.IDLE);
2912
2985
  const inPond = idle.map((item) => item.file);
2913
- if (sameFiles(inPond, current)) {
2914
- settledRef.current = current;
2986
+ if (sameFiles(inPond, current2)) {
2987
+ settledRef.current = current2;
2915
2988
  return;
2916
2989
  }
2917
- targetRef.current = current;
2918
- for (const item of idle) if (!current.includes(item.file)) pond.removeFile(item.id);
2919
- const toAdd = current.filter((file) => !inPond.includes(file));
2990
+ targetRef.current = current2;
2991
+ for (const item of idle) if (!current2.includes(item.file)) pond.removeFile(item.id);
2992
+ const toAdd = current2.filter((file) => !inPond.includes(file));
2920
2993
  if (toAdd.length > 0) void pond.addFiles(toAdd);
2921
- }, [current, pondVersion]);
2994
+ }, [current2, pondVersion]);
2922
2995
  const ready = pondVersion > 0;
2923
2996
  return /* @__PURE__ */ jsxs25(
2924
2997
  "div",
@@ -2997,15 +3070,15 @@ function rowWidth(widths, gap) {
2997
3070
  for (const w of widths) total += w;
2998
3071
  return widths.length > 1 ? total + gap * (widths.length - 1) : total;
2999
3072
  }
3000
- function fitCount({ widths, current, available, more, gap }) {
3073
+ function fitCount({ widths, current: current2, available, more, gap }) {
3001
3074
  const n = widths.length;
3002
- const hasCurrent = current >= 0 && current < n;
3075
+ const hasCurrent = current2 >= 0 && current2 < n;
3003
3076
  const others = hasCurrent ? n - 1 : n;
3004
3077
  if (rowWidth(widths, gap) <= available + EPSILON) return others;
3005
- let used = more + (hasCurrent ? widths[current] + gap : 0);
3078
+ let used = more + (hasCurrent ? widths[current2] + gap : 0);
3006
3079
  let count = 0;
3007
3080
  for (let i = 0; i < n; i++) {
3008
- if (i === current) continue;
3081
+ if (i === current2) continue;
3009
3082
  const next = used + widths[i] + gap;
3010
3083
  if (next > available + EPSILON) break;
3011
3084
  used = next;
@@ -3013,11 +3086,11 @@ function fitCount({ widths, current, available, more, gap }) {
3013
3086
  }
3014
3087
  return count;
3015
3088
  }
3016
- function inlineFlags(length, current, count) {
3089
+ function inlineFlags(length, current2, count) {
3017
3090
  const flags = [];
3018
3091
  let seen = 0;
3019
3092
  for (let i = 0; i < length; i++) {
3020
- if (i === current) flags.push(true);
3093
+ if (i === current2) flags.push(true);
3021
3094
  else flags.push(seen++ < count);
3022
3095
  }
3023
3096
  return flags;
@@ -3076,7 +3149,7 @@ function PriorityNav({
3076
3149
  ...rest
3077
3150
  }) {
3078
3151
  const signature = signatureOf(items);
3079
- const current = items.findIndex((item) => item.current);
3152
+ const current2 = items.findIndex((item) => item.current);
3080
3153
  const [fit, setFit] = useState7({ signature: null, current: -1, count: 0, overflowing: false });
3081
3154
  const [open, setOpen] = useState7(false);
3082
3155
  const panelId = useId5();
@@ -3085,7 +3158,7 @@ function PriorityNav({
3085
3158
  const toggleRef = useRef5(null);
3086
3159
  const panelRef = useRef5(null);
3087
3160
  const measured = useRef5(null);
3088
- const currentRef = useRef5(current);
3161
+ const currentRef = useRef5(current2);
3089
3162
  const fitRef = useRef5(fit);
3090
3163
  const hysteresisRef = useRef5(overflowHysteresis);
3091
3164
  const onOverflowRef = useRef5(onOverflowChange);
@@ -3095,7 +3168,7 @@ function PriorityNav({
3095
3168
  });
3096
3169
  const measuring = fit.signature !== signature;
3097
3170
  useLayoutEffect2(() => {
3098
- currentRef.current = current;
3171
+ currentRef.current = current2;
3099
3172
  fitRef.current = fit;
3100
3173
  hysteresisRef.current = overflowHysteresis;
3101
3174
  onOverflowRef.current = onOverflowChange;
@@ -3115,11 +3188,11 @@ function PriorityNav({
3115
3188
  gap: parseFloat(getComputedStyle(list).columnGap) || 0,
3116
3189
  available: list.clientWidth
3117
3190
  };
3118
- } else if (fit.current === current) return;
3191
+ } else if (fit.current === current2) return;
3119
3192
  const m = measured.current;
3120
3193
  if (!m) return;
3121
- setFit({ signature, current, ...solve(m, current, fit.overflowing) });
3122
- }, [measuring, signature, current, fit]);
3194
+ setFit({ signature, current: current2, ...solve(m, current2, fit.overflowing) });
3195
+ }, [measuring, signature, current2, fit]);
3123
3196
  useEffect5(() => {
3124
3197
  const list = listRef.current;
3125
3198
  const more = moreRef.current;
@@ -3161,7 +3234,7 @@ function PriorityNav({
3161
3234
  live = false;
3162
3235
  };
3163
3236
  }, []);
3164
- const flags = measuring ? null : inlineFlags(items.length, current, fit.count);
3237
+ const flags = measuring ? null : inlineFlags(items.length, current2, fit.count);
3165
3238
  const overflow = flags ? items.filter((_, i) => !flags[i]) : [];
3166
3239
  const expanded = open && overflow.length > 0;
3167
3240
  const overflowBadges = overflow.map(badgeOf).filter((b) => b !== null);
@@ -3336,6 +3409,7 @@ function Content3({
3336
3409
  children,
3337
3410
  ...rest
3338
3411
  }) {
3412
+ const collisionPadding = useSafeAreaPadding();
3339
3413
  return /* @__PURE__ */ jsx32(BasePopover.Portal, { children: /* @__PURE__ */ jsx32(
3340
3414
  BasePopover.Positioner,
3341
3415
  {
@@ -3344,6 +3418,7 @@ function Content3({
3344
3418
  sideOffset: sideOffset ?? (arrow ? 8 : 4),
3345
3419
  anchor,
3346
3420
  collisionAvoidance: COLLISION_AVOIDANCE,
3421
+ collisionPadding,
3347
3422
  className: "sc-popover__positioner",
3348
3423
  children: /* @__PURE__ */ jsxs27(BasePopover.Popup, { className: cx("sc-popover", className), ...rest, children: [
3349
3424
  arrow ? /* @__PURE__ */ jsx32(BasePopover.Arrow, { className: "sc-popover__arrow" }) : null,
@@ -3536,15 +3611,15 @@ function Progress2({
3536
3611
  label ? /* @__PURE__ */ jsx34("div", { className: "sc-flow__progress-label", children: label }) : null,
3537
3612
  /* @__PURE__ */ jsx34("ol", { className: "sc-flow__segments", "aria-label": listLabel, children: chapters.map((chapter, i) => {
3538
3613
  const from = starts[i];
3539
- const current = step > from && step <= from + chapter.steps;
3540
- const done = Math.min(chapter.steps, Math.max(0, step - 1 - from)) + (current ? 0.5 : 0);
3614
+ const current2 = step > from && step <= from + chapter.steps;
3615
+ const done = Math.min(chapter.steps, Math.max(0, step - 1 - from)) + (current2 ? 0.5 : 0);
3541
3616
  const percent = chapter.steps > 0 ? Math.min(100, done / chapter.steps * 100) : 0;
3542
3617
  return /* @__PURE__ */ jsxs29(
3543
3618
  "li",
3544
3619
  {
3545
3620
  className: "sc-flow__segment",
3546
3621
  style: { flexGrow: chapter.steps },
3547
- "aria-current": current ? "step" : void 0,
3622
+ "aria-current": current2 ? "step" : void 0,
3548
3623
  children: [
3549
3624
  /* @__PURE__ */ jsx34("span", { className: "sc-flow__segment-fill", style: { inlineSize: `${percent}%` } }),
3550
3625
  /* @__PURE__ */ jsx34("span", { className: "sc-visually-hidden", children: chapter.label })
@@ -3578,7 +3653,7 @@ function RailGroup({ label, className, children, ...rest }) {
3578
3653
  ] });
3579
3654
  }
3580
3655
  function RailItem({
3581
- current = false,
3656
+ current: current2 = false,
3582
3657
  done = false,
3583
3658
  doneLabel = "done",
3584
3659
  adornment,
@@ -3592,7 +3667,7 @@ function RailItem({
3592
3667
  {
3593
3668
  type,
3594
3669
  className: cx("sc-flow__rail-item", className),
3595
- "aria-current": current ? "step" : void 0,
3670
+ "aria-current": current2 ? "step" : void 0,
3596
3671
  "data-done": done || void 0,
3597
3672
  ...rest,
3598
3673
  children: [