@akhil-saxena/design-system 1.4.2 → 1.5.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.
package/dist/index.js CHANGED
@@ -542,6 +542,110 @@ function InlineEditField({
542
542
  }
543
543
  );
544
544
  }
545
+ var wrapStyle2 = { width: "100%" };
546
+ var triggerStyle = {
547
+ display: "flex",
548
+ alignItems: "center",
549
+ width: "100%",
550
+ height: 40,
551
+ border: "1px dashed var(--rule-s)",
552
+ borderRadius: "var(--radius-sm)",
553
+ padding: "0 10px",
554
+ fontFamily: "var(--font)",
555
+ fontSize: 12,
556
+ color: "var(--ink-4)",
557
+ fontStyle: "italic",
558
+ cursor: "text",
559
+ background: "none",
560
+ textAlign: "left",
561
+ boxSizing: "border-box"
562
+ };
563
+ var activeStyle = {
564
+ display: "flex",
565
+ alignItems: "center",
566
+ height: 40,
567
+ border: "1px solid var(--amber)",
568
+ borderRadius: "var(--radius-sm)",
569
+ background: "var(--panel)",
570
+ boxShadow: "var(--focus-ring)",
571
+ boxSizing: "border-box",
572
+ overflow: "hidden"
573
+ };
574
+ var inputStyle = {
575
+ flex: 1,
576
+ border: "none",
577
+ background: "transparent",
578
+ outline: "none",
579
+ fontFamily: "var(--font)",
580
+ fontSize: 12,
581
+ padding: "0 10px",
582
+ height: "100%",
583
+ color: "var(--ink)"
584
+ };
585
+ var hintStyle = {
586
+ fontFamily: "var(--mono)",
587
+ fontSize: 9,
588
+ color: "var(--ink-4)",
589
+ padding: "0 10px",
590
+ flexShrink: 0,
591
+ letterSpacing: "0.04em",
592
+ whiteSpace: "nowrap"
593
+ };
594
+ var InlineAddRow = forwardRef(function InlineAddRow2({ placeholder = "Add\u2026", onSave, kbdHint = "\u21B5 \xB7 Esc", className, style }, ref) {
595
+ const [active, setActive] = useState(false);
596
+ const [value, setValue] = useState("");
597
+ const inputRef = useRef(null);
598
+ const save = () => {
599
+ const trimmed = value.trim();
600
+ if (trimmed) onSave(trimmed);
601
+ setValue("");
602
+ setActive(false);
603
+ };
604
+ const discard = () => {
605
+ setValue("");
606
+ setActive(false);
607
+ };
608
+ const activate = () => {
609
+ setActive(true);
610
+ requestAnimationFrame(() => inputRef.current?.focus());
611
+ };
612
+ const onKeyDown = (e) => {
613
+ if (e.key === "Enter") {
614
+ e.preventDefault();
615
+ save();
616
+ }
617
+ if (e.key === "Escape") {
618
+ e.preventDefault();
619
+ discard();
620
+ }
621
+ };
622
+ return /* @__PURE__ */ jsx(
623
+ "div",
624
+ {
625
+ ref,
626
+ className: `ds-atom-inline-add${className ? ` ${className}` : ""}`,
627
+ "data-active": active,
628
+ style: { ...wrapStyle2, ...style },
629
+ children: active ? /* @__PURE__ */ jsxs("div", { style: activeStyle, children: [
630
+ /* @__PURE__ */ jsx(
631
+ "input",
632
+ {
633
+ ref: inputRef,
634
+ type: "text",
635
+ value,
636
+ onChange: (e) => setValue(e.target.value),
637
+ onKeyDown,
638
+ onBlur: discard,
639
+ placeholder,
640
+ "aria-label": placeholder,
641
+ style: inputStyle
642
+ }
643
+ ),
644
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: hintStyle, children: kbdHint })
645
+ ] }) : /* @__PURE__ */ jsx("button", { type: "button", onClick: activate, style: triggerStyle, children: placeholder })
646
+ }
647
+ );
648
+ });
545
649
  var baseStyle2 = {
546
650
  display: "inline-block",
547
651
  fontFamily: "var(--mono)",
@@ -1097,9 +1201,10 @@ function deriveGradient(seed) {
1097
1201
  const idx = djb2(seed.toLowerCase()) % AVATAR_PALETTE.length;
1098
1202
  return AVATAR_PALETTE[idx] ?? AVATAR_PALETTE[0];
1099
1203
  }
1100
- function deriveSolidColor(seed) {
1101
- const idx = djb2(seed.toLowerCase()) % SOLID_PALETTE.length;
1102
- return SOLID_PALETTE[idx] ?? SOLID_PALETTE[0];
1204
+ function deriveSolidColor(seed, palette = SOLID_PALETTE) {
1205
+ const pool = palette.length > 0 ? palette : SOLID_PALETTE;
1206
+ const idx = djb2(seed.toLowerCase()) % pool.length;
1207
+ return pool[idx] ?? pool[0] ?? SOLID_PALETTE[0];
1103
1208
  }
1104
1209
  var presenceColors = {
1105
1210
  online: "var(--green-vivid)",
@@ -1110,6 +1215,8 @@ var presenceColors = {
1110
1215
  var Avatar = forwardRef(function Avatar2({
1111
1216
  name,
1112
1217
  initials,
1218
+ seed,
1219
+ palette,
1113
1220
  src,
1114
1221
  alt,
1115
1222
  gradient,
@@ -1120,14 +1227,14 @@ var Avatar = forwardRef(function Avatar2({
1120
1227
  style,
1121
1228
  ...rest
1122
1229
  }, ref) {
1123
- const seed = initials || name || "?";
1230
+ const colorSeed = seed || initials || name || "?";
1124
1231
  const computedInitials = initials ?? deriveInitials(name);
1125
1232
  let background;
1126
1233
  if (gradient) {
1127
- const stops = Array.isArray(gradient) ? gradient : deriveGradient(seed);
1234
+ const stops = Array.isArray(gradient) ? gradient : deriveGradient(colorSeed);
1128
1235
  background = `linear-gradient(145deg, ${stops[0]}, ${stops[1]})`;
1129
1236
  } else {
1130
- background = deriveSolidColor(seed);
1237
+ background = deriveSolidColor(colorSeed, palette);
1131
1238
  }
1132
1239
  const containerStyle = {
1133
1240
  position: "relative",
@@ -1234,7 +1341,7 @@ var labelStyle = {
1234
1341
  color: "var(--ink)",
1235
1342
  userSelect: "none"
1236
1343
  };
1237
- var inputStyle = {
1344
+ var inputStyle2 = {
1238
1345
  position: "absolute",
1239
1346
  width: 1,
1240
1347
  height: 1,
@@ -1281,7 +1388,7 @@ var Checkbox = forwardRef(function Checkbox2({ label, className, disabled, style
1281
1388
  type: "checkbox",
1282
1389
  className: "ds-atom-checkbox-input",
1283
1390
  disabled,
1284
- style: inputStyle,
1391
+ style: inputStyle2,
1285
1392
  ...rest
1286
1393
  }
1287
1394
  ),
@@ -1341,7 +1448,7 @@ var labelStyle2 = {
1341
1448
  color: "var(--ink)",
1342
1449
  userSelect: "none"
1343
1450
  };
1344
- var inputStyle2 = {
1451
+ var inputStyle3 = {
1345
1452
  position: "absolute",
1346
1453
  width: 1,
1347
1454
  height: 1,
@@ -1393,7 +1500,7 @@ var Radio = forwardRef(function Radio2({ label, className, disabled, value, name
1393
1500
  ctx?.onChange(value, e);
1394
1501
  onChange?.(e);
1395
1502
  },
1396
- style: inputStyle2,
1503
+ style: inputStyle3,
1397
1504
  ...rest
1398
1505
  }
1399
1506
  ),
@@ -1413,7 +1520,7 @@ var labelStyle3 = {
1413
1520
  color: "var(--ink)",
1414
1521
  userSelect: "none"
1415
1522
  };
1416
- var inputStyle3 = {
1523
+ var inputStyle4 = {
1417
1524
  position: "absolute",
1418
1525
  width: 1,
1419
1526
  height: 1,
@@ -1446,7 +1553,7 @@ var Toggle = forwardRef(function Toggle2({ label, className, disabled, style, ch
1446
1553
  disabled,
1447
1554
  checked,
1448
1555
  defaultChecked,
1449
- style: inputStyle3,
1556
+ style: inputStyle4,
1450
1557
  ...rest
1451
1558
  }
1452
1559
  ),
@@ -3104,6 +3211,7 @@ function BottomSheet({
3104
3211
  height = "half",
3105
3212
  closeOnBackdropClick = true,
3106
3213
  dark,
3214
+ trackKeyboard = true,
3107
3215
  className,
3108
3216
  style
3109
3217
  }) {
@@ -3115,6 +3223,7 @@ function BottomSheet({
3115
3223
  const dragStateRef = useRef(null);
3116
3224
  const [dragOffset, setDragOffset] = useState(0);
3117
3225
  const [dragging, setDragging] = useState(false);
3226
+ const [kbOffset, setKbOffset] = useState(0);
3118
3227
  function handleHandlePointerDown(e) {
3119
3228
  if (!panelNode) return;
3120
3229
  dragStateRef.current = {
@@ -3160,6 +3269,22 @@ function BottomSheet({
3160
3269
  document.addEventListener("keydown", onKey);
3161
3270
  return () => document.removeEventListener("keydown", onKey);
3162
3271
  }, [open, onClose]);
3272
+ useEffect(() => {
3273
+ if (!open || !trackKeyboard) return;
3274
+ if (typeof window === "undefined") return;
3275
+ const vv = window.visualViewport;
3276
+ if (!vv) return;
3277
+ const update = () => {
3278
+ const offset = window.innerHeight - vv.height - (vv.offsetTop ?? 0);
3279
+ setKbOffset(Math.max(0, offset));
3280
+ };
3281
+ vv.addEventListener("resize", update);
3282
+ update();
3283
+ return () => {
3284
+ vv.removeEventListener("resize", update);
3285
+ setKbOffset(0);
3286
+ };
3287
+ }, [open, trackKeyboard]);
3163
3288
  if (!open) return null;
3164
3289
  const isDark = dark ?? document.documentElement.classList.contains("dark");
3165
3290
  function handleBackdropClick(e) {
@@ -3202,7 +3327,14 @@ function BottomSheet({
3202
3327
  ),
3203
3328
  title ? /* @__PURE__ */ jsx("header", { id: titleId, className: "ds-atom-bottomsheet-hd", children: title }) : null,
3204
3329
  /* @__PURE__ */ jsx("div", { className: "ds-atom-bottomsheet-body", children }),
3205
- footer ? /* @__PURE__ */ jsx("footer", { className: "ds-atom-bottomsheet-ft", children: footer }) : null
3330
+ footer ? /* @__PURE__ */ jsx(
3331
+ "footer",
3332
+ {
3333
+ className: "ds-atom-bottomsheet-ft",
3334
+ style: kbOffset > 0 ? { paddingBottom: `${kbOffset}px` } : void 0,
3335
+ children: footer
3336
+ }
3337
+ ) : null
3206
3338
  ]
3207
3339
  }
3208
3340
  )
@@ -3210,6 +3342,153 @@ function BottomSheet({
3210
3342
  ) });
3211
3343
  return /* @__PURE__ */ jsx(DSPortal, { children: isDark ? /* @__PURE__ */ jsx("div", { className: "dark", children: sheetEl }) : sheetEl });
3212
3344
  }
3345
+ var KEYFRAMES = `
3346
+ @keyframes ds-actionsheet-backdrop { from { opacity: 0 } to { opacity: 1 } }
3347
+ @keyframes ds-actionsheet-enter { from { transform: translateY(30px); opacity: 0 } to { transform: translateY(0); opacity: 1 } }
3348
+ @keyframes ds-actionsheet-enter-delayed { 0% { transform: translateY(30px); opacity: 0 } 8.3% { transform: translateY(30px); opacity: 0 } 100% { transform: translateY(0); opacity: 1 } }
3349
+ @media (prefers-reduced-motion: reduce) {
3350
+ .ds-actionsheet-backdrop, .ds-actionsheet-items, .ds-actionsheet-cancel { animation: none !important }
3351
+ }
3352
+ `;
3353
+ var blockStyle = {
3354
+ borderRadius: "var(--radius-lg)",
3355
+ background: "var(--panel)",
3356
+ overflow: "hidden",
3357
+ boxShadow: "var(--shadow-3)"
3358
+ };
3359
+ var itemBase = {
3360
+ display: "block",
3361
+ width: "100%",
3362
+ minHeight: 56,
3363
+ background: "var(--panel)",
3364
+ border: "none",
3365
+ fontFamily: "var(--font)",
3366
+ fontSize: 17,
3367
+ textAlign: "center",
3368
+ cursor: "pointer",
3369
+ padding: "0 16px"
3370
+ };
3371
+ function ActionSheet({ open, onClose, items, cancelLabel = "Close" }) {
3372
+ const [mounted, setMounted] = useState(false);
3373
+ const [visible, setVisible] = useState(false);
3374
+ useEffect(() => setMounted(true), []);
3375
+ useEffect(() => {
3376
+ if (open) {
3377
+ setVisible(true);
3378
+ return;
3379
+ }
3380
+ const t = setTimeout(() => setVisible(false), 260);
3381
+ return () => clearTimeout(t);
3382
+ }, [open]);
3383
+ useEffect(() => {
3384
+ document.body.style.overflow = open ? "hidden" : "";
3385
+ return () => {
3386
+ document.body.style.overflow = "";
3387
+ };
3388
+ }, [open]);
3389
+ useEffect(() => {
3390
+ if (!open) return;
3391
+ const handler = (e) => {
3392
+ if (e.key === "Escape") onClose();
3393
+ };
3394
+ window.addEventListener("keydown", handler);
3395
+ return () => window.removeEventListener("keydown", handler);
3396
+ }, [open, onClose]);
3397
+ if (!mounted || !visible) return null;
3398
+ const fade = {
3399
+ opacity: open ? 1 : 0,
3400
+ transition: open ? void 0 : "opacity 260ms ease-in"
3401
+ };
3402
+ return createPortal(
3403
+ /* @__PURE__ */ jsxs(Fragment, { children: [
3404
+ /* @__PURE__ */ jsx("style", { children: KEYFRAMES }),
3405
+ /* @__PURE__ */ jsx(
3406
+ "div",
3407
+ {
3408
+ "aria-hidden": "true",
3409
+ className: "ds-actionsheet-backdrop",
3410
+ onClick: onClose,
3411
+ style: {
3412
+ position: "fixed",
3413
+ inset: 0,
3414
+ background: "rgba(0,0,0,0.18)",
3415
+ zIndex: 60,
3416
+ animation: open ? "ds-actionsheet-backdrop 240ms ease-out both" : void 0,
3417
+ ...fade
3418
+ }
3419
+ }
3420
+ ),
3421
+ /* @__PURE__ */ jsxs(
3422
+ "div",
3423
+ {
3424
+ style: {
3425
+ position: "fixed",
3426
+ left: 8,
3427
+ right: 8,
3428
+ bottom: "calc(8px + env(safe-area-inset-bottom))",
3429
+ zIndex: 61,
3430
+ display: "flex",
3431
+ flexDirection: "column",
3432
+ gap: 8
3433
+ },
3434
+ children: [
3435
+ /* @__PURE__ */ jsx(
3436
+ "div",
3437
+ {
3438
+ role: "menu",
3439
+ className: "ds-actionsheet-items",
3440
+ style: {
3441
+ ...blockStyle,
3442
+ animation: open ? "ds-actionsheet-enter 240ms cubic-bezier(0.32,0.72,0,1) both" : void 0,
3443
+ ...fade
3444
+ },
3445
+ children: items.map((item, idx) => /* @__PURE__ */ jsx(
3446
+ "button",
3447
+ {
3448
+ type: "button",
3449
+ role: "menuitem",
3450
+ onClick: () => {
3451
+ item.onSelect();
3452
+ onClose();
3453
+ },
3454
+ style: {
3455
+ ...itemBase,
3456
+ borderBottom: idx < items.length - 1 ? "1px solid var(--rule)" : "none",
3457
+ color: item.variant === "destructive" ? "var(--red)" : "var(--ink)"
3458
+ },
3459
+ children: item.label
3460
+ },
3461
+ item.label
3462
+ ))
3463
+ }
3464
+ ),
3465
+ /* @__PURE__ */ jsx(
3466
+ "div",
3467
+ {
3468
+ className: "ds-actionsheet-cancel",
3469
+ style: {
3470
+ ...blockStyle,
3471
+ animation: open ? "ds-actionsheet-enter-delayed 240ms cubic-bezier(0.32,0.72,0,1) both" : void 0,
3472
+ ...fade
3473
+ },
3474
+ children: /* @__PURE__ */ jsx(
3475
+ "button",
3476
+ {
3477
+ type: "button",
3478
+ onClick: onClose,
3479
+ style: { ...itemBase, fontWeight: 600, color: "var(--ink)" },
3480
+ children: cancelLabel
3481
+ }
3482
+ )
3483
+ }
3484
+ )
3485
+ ]
3486
+ }
3487
+ )
3488
+ ] }),
3489
+ document.body
3490
+ );
3491
+ }
3213
3492
  function Lightbox({ open, onClose, items, activeIndex = 0, onIndexChange }) {
3214
3493
  const closeButtonRef = useRef(null);
3215
3494
  const length = items.length;
@@ -3730,6 +4009,7 @@ function SnackbarProvider({ children }) {
3730
4009
  action,
3731
4010
  duration,
3732
4011
  dismissible,
4012
+ progress: opts?.progress ?? false,
3733
4013
  dismissing: false
3734
4014
  });
3735
4015
  if (Number.isFinite(duration)) {
@@ -3769,9 +4049,27 @@ function SnackbarProvider({ children }) {
3769
4049
  ) }) }) : null
3770
4050
  ] });
3771
4051
  }
4052
+ var PROGRESS_COLOR = {
4053
+ neutral: "var(--amber)",
4054
+ success: "var(--green, #1f8a5b)",
4055
+ error: "var(--red, #9b2c2c)"
4056
+ };
4057
+ var PROGRESS_STYLE = `
4058
+ @keyframes ds-atom-snackbar-progress {
4059
+ from { transform: scaleX(1); }
4060
+ to { transform: scaleX(0); }
4061
+ }
4062
+ @media (prefers-reduced-motion: reduce) {
4063
+ .ds-atom-snackbar-progress {
4064
+ animation: none !important;
4065
+ transform: scaleX(1) !important;
4066
+ }
4067
+ }
4068
+ `;
3772
4069
  function SnackbarNode({ entry, onAction, onDismiss }) {
3773
4070
  const role = entry.tone === "error" ? "alert" : "status";
3774
4071
  const ariaLive = role === "alert" ? "assertive" : "polite";
4072
+ const showProgress = entry.progress && Number.isFinite(entry.duration);
3775
4073
  return /* @__PURE__ */ jsxs(
3776
4074
  "div",
3777
4075
  {
@@ -3780,6 +4078,7 @@ function SnackbarNode({ entry, onAction, onDismiss }) {
3780
4078
  "data-dismissing": entry.dismissing ? "true" : void 0,
3781
4079
  role,
3782
4080
  "aria-live": ariaLive,
4081
+ style: showProgress ? { position: "relative", overflow: "hidden" } : void 0,
3783
4082
  children: [
3784
4083
  /* @__PURE__ */ jsx("span", { className: "ds-atom-snackbar-msg", children: entry.message }),
3785
4084
  entry.action ? /* @__PURE__ */ jsx("button", { type: "button", className: "ds-atom-snackbar-action", onClick: onAction, children: entry.action.label }) : null,
@@ -3792,7 +4091,29 @@ function SnackbarNode({ entry, onAction, onDismiss }) {
3792
4091
  onClick: onDismiss,
3793
4092
  children: /* @__PURE__ */ jsx(X, { size: 14, "aria-hidden": "true" })
3794
4093
  }
3795
- ) : null
4094
+ ) : null,
4095
+ showProgress ? /* @__PURE__ */ jsxs(Fragment, { children: [
4096
+ /* @__PURE__ */ jsx("style", { children: PROGRESS_STYLE }),
4097
+ /* @__PURE__ */ jsx(
4098
+ "span",
4099
+ {
4100
+ className: "ds-atom-snackbar-progress",
4101
+ "data-testid": "ds-atom-snackbar-progress",
4102
+ "aria-hidden": "true",
4103
+ style: {
4104
+ position: "absolute",
4105
+ left: 0,
4106
+ bottom: 0,
4107
+ height: 2,
4108
+ width: "100%",
4109
+ transformOrigin: "left",
4110
+ background: PROGRESS_COLOR[entry.tone],
4111
+ // Pause depletion once dismissing so the slide-out reads cleanly.
4112
+ animation: entry.dismissing ? void 0 : `ds-atom-snackbar-progress ${entry.duration}ms linear forwards`
4113
+ }
4114
+ }
4115
+ )
4116
+ ] }) : null
3796
4117
  ]
3797
4118
  }
3798
4119
  );
@@ -5141,7 +5462,7 @@ function FileInput({
5141
5462
  }
5142
5463
  );
5143
5464
  }
5144
- const triggerStyle = {
5465
+ const triggerStyle2 = {
5145
5466
  width: "100%",
5146
5467
  padding: 18,
5147
5468
  background: dragOver ? "var(--paper-deep)" : "var(--paper-warm)",
@@ -5185,7 +5506,7 @@ function FileInput({
5185
5506
  if (disabled) return;
5186
5507
  handlePickedFiles(e.dataTransfer.files);
5187
5508
  },
5188
- style: triggerStyle,
5509
+ style: triggerStyle2,
5189
5510
  children: children ?? /* @__PURE__ */ jsx(DefaultDropzoneContent, {})
5190
5511
  }
5191
5512
  ),
@@ -5806,6 +6127,7 @@ function SegmentedControlInner({
5806
6127
  children: options.map((opt, i) => {
5807
6128
  const isActive = opt.value === value;
5808
6129
  const tabIndex = activeIndex >= 0 ? isActive ? 0 : -1 : i === fallbackTabIndex ? 0 : -1;
6130
+ const toneStyle = isActive && opt.tone ? { background: opt.tone.activeBg, color: opt.tone.fg } : void 0;
5809
6131
  return /* @__PURE__ */ jsx(
5810
6132
  "button",
5811
6133
  {
@@ -5815,6 +6137,8 @@ function SegmentedControlInner({
5815
6137
  tabIndex,
5816
6138
  disabled: disabled || opt.disabled,
5817
6139
  "data-active": isActive ? "true" : void 0,
6140
+ "data-toned": isActive && opt.tone ? "true" : void 0,
6141
+ style: toneStyle,
5818
6142
  onClick: () => {
5819
6143
  if (!disabled && !opt.disabled) onChange(opt.value);
5820
6144
  },
@@ -10757,6 +11081,15 @@ lowlight.register("ts", typescript);
10757
11081
  lowlight.register("typescript", typescript);
10758
11082
  lowlight.register("json", json);
10759
11083
  lowlight.register("python", python);
11084
+ var HINT_ITEMS = [
11085
+ { key: "\u2318B", label: "Bold" },
11086
+ { key: "\u2318I", label: "Italic" },
11087
+ { key: "\u2318U", label: "Underline" },
11088
+ { key: "\u2318\u21E7H", label: "Highlight" },
11089
+ { key: "\u2318K", label: "Link" },
11090
+ { key: "\u2318\u21B5", label: "Save" },
11091
+ { key: "Esc", label: "Discard" }
11092
+ ];
10760
11093
  var CODE_LANGUAGES = [
10761
11094
  { value: "plaintext", label: "Plain text" },
10762
11095
  { value: "javascript", label: "JavaScript" },
@@ -10780,7 +11113,9 @@ var RichText = forwardRef(function RichText2({
10780
11113
  toolbar,
10781
11114
  className,
10782
11115
  ariaLabel = "Rich text editor",
10783
- style
11116
+ style,
11117
+ inline = false,
11118
+ hints = false
10784
11119
  }, ref) {
10785
11120
  const lastEmittedRef = useRef(typeof value === "string" ? value : "");
10786
11121
  const linkBtnRef = useRef(null);
@@ -10790,6 +11125,7 @@ var RichText = forwardRef(function RichText2({
10790
11125
  const [headingOpen, setHeadingOpen] = useState(false);
10791
11126
  const [headingActiveIndex, setHeadingActiveIndex] = useState(0);
10792
11127
  const [codeBlockDark, setCodeBlockDark] = useState(false);
11128
+ const [focused, setFocused] = useState(false);
10793
11129
  const editor = useEditor({
10794
11130
  extensions: [
10795
11131
  // Disable StarterKit's bundled Link and Underline so we can configure them ourselves.
@@ -10808,6 +11144,9 @@ var RichText = forwardRef(function RichText2({
10808
11144
  editable: !readOnly,
10809
11145
  // MANDATORY: SSR-safe per D-17-19. Without this TipTap throws during SSR hydration.
10810
11146
  immediatelyRender: false,
11147
+ // Focus tracking only drives the optional `hints` strip; no behavioral impact when off.
11148
+ onFocus: () => setFocused(true),
11149
+ onBlur: () => setFocused(false),
10811
11150
  onUpdate: ({ editor: editor2 }) => {
10812
11151
  if (outputFormat === "json") {
10813
11152
  onChange(editor2.getJSON());
@@ -11134,30 +11473,84 @@ var RichText = forwardRef(function RichText2({
11134
11473
  ]
11135
11474
  }
11136
11475
  ) }) : null;
11476
+ const inlineRootStyle = inline ? { border: "none", borderRadius: 0, background: "transparent", overflow: "visible" } : void 0;
11477
+ const inlineSurfaceStyle = inline ? { padding: 0, minHeight: 0 } : void 0;
11478
+ const hintStrip = hints && !readOnly ? /* @__PURE__ */ jsx(
11479
+ "div",
11480
+ {
11481
+ className: "ds-atom-richtext-hints",
11482
+ "aria-hidden": "true",
11483
+ style: {
11484
+ display: "flex",
11485
+ alignItems: "center",
11486
+ flexWrap: "wrap",
11487
+ gap: 14,
11488
+ paddingLeft: inline ? 0 : 12,
11489
+ paddingRight: inline ? 0 : 12,
11490
+ // Collapse vertical space when unfocused so the default (unfocused)
11491
+ // layout is unchanged; reveal on focus.
11492
+ paddingTop: focused ? 6 : 0,
11493
+ paddingBottom: focused ? inline ? 0 : 6 : 0,
11494
+ borderTop: inline ? "none" : "1px solid var(--rule)",
11495
+ fontFamily: "var(--mono)",
11496
+ fontSize: 9.5,
11497
+ color: "var(--ink-4)",
11498
+ letterSpacing: "0.03em",
11499
+ opacity: focused ? 1 : 0,
11500
+ maxHeight: focused ? 200 : 0,
11501
+ overflow: "hidden",
11502
+ transition: "opacity 0.15s ease, max-height 0.15s ease"
11503
+ },
11504
+ children: HINT_ITEMS.map((h) => /* @__PURE__ */ jsxs(
11505
+ "span",
11506
+ {
11507
+ style: { display: "inline-flex", alignItems: "center", gap: 5, color: "var(--ink-3)" },
11508
+ children: [
11509
+ /* @__PURE__ */ jsx(Kbd, { size: "sm", children: h.key }),
11510
+ h.label
11511
+ ]
11512
+ },
11513
+ h.key
11514
+ ))
11515
+ }
11516
+ ) : null;
11137
11517
  if (!editor) {
11138
11518
  return /* @__PURE__ */ jsx(
11139
11519
  "div",
11140
11520
  {
11141
11521
  ref,
11142
11522
  className: `ds-atom-richtext ds-atom-richtext--loading${className ? ` ${className}` : ""}`,
11143
- style,
11523
+ style: { ...inlineRootStyle, ...style },
11524
+ "data-inline": inline || void 0,
11144
11525
  "aria-label": ariaLabel,
11145
11526
  "aria-busy": "true"
11146
11527
  }
11147
11528
  );
11148
11529
  }
11149
- return /* @__PURE__ */ jsxs("div", { ref, className: "ds-atom-richtext", style, "aria-label": ariaLabel, children: [
11150
- !readOnly && (toolbar ?? defaultToolbar),
11151
- /* @__PURE__ */ jsx(
11152
- "div",
11153
- {
11154
- className: ["ds-atom-richtext-surface", className].filter(Boolean).join(" "),
11155
- "data-code-dark": codeBlockDark || void 0,
11156
- children: /* @__PURE__ */ jsx(EditorContent, { editor })
11157
- }
11158
- ),
11159
- linkPopover
11160
- ] });
11530
+ return /* @__PURE__ */ jsxs(
11531
+ "div",
11532
+ {
11533
+ ref,
11534
+ className: "ds-atom-richtext",
11535
+ style: { ...inlineRootStyle, ...style },
11536
+ "data-inline": inline || void 0,
11537
+ "aria-label": ariaLabel,
11538
+ children: [
11539
+ !readOnly && (toolbar ?? defaultToolbar),
11540
+ /* @__PURE__ */ jsx(
11541
+ "div",
11542
+ {
11543
+ className: ["ds-atom-richtext-surface", className].filter(Boolean).join(" "),
11544
+ "data-code-dark": codeBlockDark || void 0,
11545
+ style: inlineSurfaceStyle,
11546
+ children: /* @__PURE__ */ jsx(EditorContent, { editor })
11547
+ }
11548
+ ),
11549
+ hintStrip,
11550
+ linkPopover
11551
+ ]
11552
+ }
11553
+ );
11161
11554
  });
11162
11555
  function readStorage(storageKey) {
11163
11556
  if (storageKey === null || storageKey === void 0) return false;
@@ -11845,6 +12238,6 @@ function Sortable({ items, onReorder, renderItem, id, className, style }) {
11845
12238
  );
11846
12239
  }
11847
12240
 
11848
- export { Accordion2 as Accordion, AlertBanner, AppBar, AppShell, Autocomplete, Avatar, AvatarStack, Badge, BottomSheet, Breadcrumbs, Button, Calendar, Card, Carousel, Checkbox, Chip, Coachmark, ColorInput, ColorPicker, CommandPalette, ConfirmDialog, ContextMenu, CopyToClipboard, DSPortal, DataGrid, DatePicker, DateRangePicker, Divider, DotGrid, EmptyState, Eyebrow, FieldError, FileInput, Footer, FormErrorSummary, Heading, HoverCard, InfiniteList, InlineConfirm, InlineEdit, InlineEditField, Kbd, Lightbox, Link, MiniBar, MiniDonut, Modal, MultiSelect, NumberStepper, OAuthButton, Pagination, PasswordStrength, Popover, ProgressBar, Radio, RadioGroup, RangeSlider, RelativeTime, RichText, RollingNumber, SearchAndFilters, SegmentedControl, Select, Sheet, Skeleton, SnackbarProvider, Sortable, SortableDndContext, SortableItem, Sparkline, SplitButton, SplitHero, StarRating, StatCard, StatusPill, StickyNote, Table, Tabs, Text, TextInput, Textarea, Timeline, ToastProvider, Toggle, Tooltip, TypeToConfirm, Wizard, deriveGradient, deriveInitials, useSnackbar, useToast };
12241
+ export { Accordion2 as Accordion, ActionSheet, AlertBanner, AppBar, AppShell, Autocomplete, Avatar, AvatarStack, Badge, BottomSheet, Breadcrumbs, Button, Calendar, Card, Carousel, Checkbox, Chip, Coachmark, ColorInput, ColorPicker, CommandPalette, ConfirmDialog, ContextMenu, CopyToClipboard, DSPortal, DataGrid, DatePicker, DateRangePicker, Divider, DotGrid, EmptyState, Eyebrow, FieldError, FileInput, Footer, FormErrorSummary, Heading, HoverCard, InfiniteList, InlineAddRow, InlineConfirm, InlineEdit, InlineEditField, Kbd, Lightbox, Link, MiniBar, MiniDonut, Modal, MultiSelect, NumberStepper, OAuthButton, Pagination, PasswordStrength, Popover, ProgressBar, Radio, RadioGroup, RangeSlider, RelativeTime, RichText, RollingNumber, SearchAndFilters, SegmentedControl, Select, Sheet, Skeleton, SnackbarProvider, Sortable, SortableDndContext, SortableItem, Sparkline, SplitButton, SplitHero, StarRating, StatCard, StatusPill, StickyNote, Table, Tabs, Text, TextInput, Textarea, Timeline, ToastProvider, Toggle, Tooltip, TypeToConfirm, Wizard, deriveGradient, deriveInitials, useSnackbar, useToast };
11849
12242
  //# sourceMappingURL=index.js.map
11850
12243
  //# sourceMappingURL=index.js.map