@caratlogic/design-system 0.1.9 → 0.1.10

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.esm.js CHANGED
@@ -5742,21 +5742,33 @@ const TextHyperlink = ({ to, href, children, showIcon = true, className, 'aria-l
5742
5742
  return (jsx("a", { href: href, target: "_blank", rel: "noopener noreferrer", "aria-label": ariaLabel, className: cn(LINK_CLASS, className), children: content }));
5743
5743
  };
5744
5744
 
5745
+ /**
5746
+ * Track, thumb and travel, sized so the thumb keeps an even 2px inset on all
5747
+ * four sides. Travel is stated in px rather than `calc(100% - Npx)`: that form
5748
+ * resolves against the thumb's own width, so the gap silently changed whenever a
5749
+ * thumb size did — `md` ended up with a 0.2px vertical inset and no gap at
5750
+ * either end, which read as a thumb bulging out of its track.
5751
+ *
5752
+ * inner = track - 2px border | thumb = innerHeight - 4 | on = innerWidth - thumb - 2
5753
+ */
5745
5754
  const switchSizes = {
5755
+ // track 28x16 → inner 26x14, thumb 10, on 14
5746
5756
  sm: {
5747
5757
  switch: 'h-4 w-7',
5748
- thumb: 'size-3',
5749
- translate: 'data-[state=checked]:translate-x-[calc(100%-1px)]',
5758
+ thumb: 'size-2.5',
5759
+ translate: 'data-[state=unchecked]:translate-x-[2px] data-[state=checked]:translate-x-[14px]',
5750
5760
  },
5761
+ // track 32x20 → inner 30x18, thumb 14, on 14
5751
5762
  md: {
5752
- switch: 'h-[1.15rem] w-8',
5753
- thumb: 'size-4',
5754
- translate: 'data-[state=checked]:translate-x-[calc(100%-2px)]',
5763
+ switch: 'h-5 w-8',
5764
+ thumb: 'size-3.5',
5765
+ translate: 'data-[state=unchecked]:translate-x-[2px] data-[state=checked]:translate-x-[14px]',
5755
5766
  },
5767
+ // track 44x24 → inner 42x22, thumb 18, on 22
5756
5768
  lg: {
5757
5769
  switch: 'h-6 w-11',
5758
- thumb: 'size-5',
5759
- translate: 'data-[state=checked]:translate-x-[calc(100%-3px)]',
5770
+ thumb: 'size-[1.125rem]',
5771
+ translate: 'data-[state=unchecked]:translate-x-[2px] data-[state=checked]:translate-x-[22px]',
5760
5772
  },
5761
5773
  };
5762
5774
 
@@ -5767,7 +5779,7 @@ function ToggleSwitch({ checked = false, onCheckedChange, disabled = false, id,
5767
5779
  }
5768
5780
  };
5769
5781
  const currentSize = switchSizes[size];
5770
- const switchButton = (jsx("button", { type: "button", role: "switch", "aria-checked": checked, "data-state": checked ? 'checked' : 'unchecked', value: checked ? 'on' : 'off', "data-slot": "switch", disabled: disabled, onClick: handleClick, id: id, name: name, className: cn('peer inline-flex shrink-0 cursor-pointer items-center rounded-full border border-transparent transition-all outline-none', 'focus-visible:ring-ring/50 focus-visible:border-ring focus-visible:ring-[3px]', 'disabled:cursor-not-allowed disabled:opacity-50', 'data-[state=unchecked]:bg-muted', 'data-[state=checked]:bg-primary', currentSize.switch, className), ...props, children: jsx("span", { "data-state": checked ? 'checked' : 'unchecked', "data-slot": "switch-thumb", className: cn('pointer-events-none block rounded-full ring-0 transition-transform', 'bg-card data-[state=checked]:bg-primary-foreground', 'data-[state=unchecked]:translate-x-0', currentSize.thumb, currentSize.translate) }) }));
5782
+ const switchButton = (jsx("button", { type: "button", role: "switch", "aria-checked": checked, "data-state": checked ? 'checked' : 'unchecked', value: checked ? 'on' : 'off', "data-slot": "switch", disabled: disabled, onClick: handleClick, id: id, name: name, className: cn('peer inline-flex shrink-0 cursor-pointer items-center rounded-full border border-transparent transition-all outline-none', 'focus-visible:ring-ring/50 focus-visible:border-ring focus-visible:ring-[3px]', 'disabled:cursor-not-allowed disabled:opacity-50', 'data-[state=unchecked]:bg-muted', 'data-[state=checked]:bg-primary', currentSize.switch, className), ...props, children: jsx("span", { "data-state": checked ? 'checked' : 'unchecked', "data-slot": "switch-thumb", className: cn('pointer-events-none block rounded-full ring-0 transition-transform', 'bg-card data-[state=checked]:bg-primary-foreground', currentSize.thumb, currentSize.translate) }) }));
5771
5783
  if (!label) {
5772
5784
  return switchButton;
5773
5785
  }
@@ -58436,33 +58448,39 @@ function ZoomSplitViewer({ src, alt = 'Preview', zoom = 2, lensSize = 160, paneO
58436
58448
  }) })), isTouchDevice && (jsx("p", { className: `text-xs text-muted-foreground text-center mt-2 ${isMobile ? 'text-2xs' : ''}`, children: isMobile ? 'Touch & hold to zoom' : 'Touch and hold to zoom' }))] }));
58437
58449
  }
58438
58450
 
58439
- const SIZE_MAP = {
58440
- sm: {
58441
- track: { width: 28, height: 16 },
58442
- thumb: 12,
58443
- on: 14,
58444
- off: 2,
58445
- },
58446
- md: {
58447
- track: { width: 44, height: 24 },
58448
- thumb: 20,
58449
- on: 22,
58450
- off: 2,
58451
- },
58452
- lg: {
58453
- track: { width: 52, height: 28 },
58454
- thumb: 24,
58455
- on: 26,
58456
- off: 2,
58457
- },
58451
+ /** 1px border on the track, and the gap between thumb and track. */
58452
+ const TRACK_BORDER = 1;
58453
+ const THUMB_INSET = 2;
58454
+ const TRACK_SIZE = {
58455
+ sm: { width: 28, height: 16 },
58456
+ md: { width: 44, height: 24 },
58457
+ lg: { width: 52, height: 28 },
58458
58458
  };
58459
+ /**
58460
+ * Thumb size and travel are derived from the track rather than listed per size:
58461
+ * hardcoding them left the thumb 1px from the top and bottom but flush against
58462
+ * the inner right edge when on, so it bulged past the track's rounded end.
58463
+ * Deriving keeps the inset equal on all four sides at every size.
58464
+ */
58465
+ function switchGeometry(size) {
58466
+ const track = TRACK_SIZE[size];
58467
+ const innerWidth = track.width - TRACK_BORDER * 2;
58468
+ const innerHeight = track.height - TRACK_BORDER * 2;
58469
+ const thumb = innerHeight - THUMB_INSET * 2;
58470
+ return {
58471
+ track,
58472
+ thumb,
58473
+ off: THUMB_INSET,
58474
+ on: innerWidth - thumb - THUMB_INSET,
58475
+ };
58476
+ }
58459
58477
  const Switch = React.forwardRef(({ checked = false, onCheckedChange, disabled = false, id, name, className, size = 'md', 'aria-label': ariaLabel, }, ref) => {
58460
58478
  const handleClick = () => {
58461
58479
  if (!disabled && onCheckedChange) {
58462
58480
  onCheckedChange(!checked);
58463
58481
  }
58464
58482
  };
58465
- const dims = SIZE_MAP[size];
58483
+ const dims = switchGeometry(size);
58466
58484
  return (jsx("button", { type: "button", role: "switch", "aria-checked": checked, "aria-label": ariaLabel, "data-state": checked ? 'checked' : 'unchecked', disabled: disabled, onClick: handleClick, ref: ref, id: id, name: name, style: {
58467
58485
  width: dims.track.width,
58468
58486
  height: dims.track.height,
@@ -66086,7 +66104,13 @@ function CreateFormPageHeader({ title, onBack, backLabel = 'Go back', }) {
66086
66104
  function CreateFormPageShell({ title, onBack, children, backLabel, scrollable = false, containerClassName, }) {
66087
66105
  const content = (jsxs("div", { className: cn('mx-auto w-full max-w-4xl px-4 py-4', containerClassName), children: [jsx(CreateFormPageHeader, { title: title, onBack: onBack, backLabel: backLabel }), children] }));
66088
66106
  if (scrollable) {
66089
- return (jsx("div", { className: "h-full min-h-0 overflow-y-auto bg-card", children: content }));
66107
+ // `shrink-0` is the load-bearing part. As a flex item in the shell's
66108
+ // `flex-col overflow-y-auto` parent this div was shrunk to the parent's
66109
+ // height while its content overflowed, so the background stopped one
66110
+ // screenful down and taller forms showed the page background below it.
66111
+ // `min-h-full` alone cannot fix that — it resolves to the same shrunken
66112
+ // height. The parent already scrolls, so no inner scroller is needed.
66113
+ return (jsx("div", { className: "min-h-full shrink-0 bg-card", children: content }));
66090
66114
  }
66091
66115
  return content;
66092
66116
  }