gridsmith-ui 0.11.0 → 0.13.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
@@ -1,5 +1,5 @@
1
- import { useAppShell, ControlSizeContext, Button, Spinner, DrawerFooterCtx, useCompact, useElementWidth, Sheet, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, useDirtyGuard, DiscardConfirm, defaultMaxWidth } from './chunk-YMUCTZXS.js';
2
- export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell } from './chunk-YMUCTZXS.js';
1
+ import { useAppShell, ControlSizeContext, Button, Spinner, OverlayCloseCtx, DrawerFooterCtx, useCompact, useElementWidth, Sheet, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, useDirtyGuard, DiscardConfirm, defaultMaxWidth } from './chunk-KKTIRPNZ.js';
2
+ export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell } from './chunk-KKTIRPNZ.js';
3
3
  import { Skeleton } from './chunk-M3AARGLI.js';
4
4
  export { Skeleton } from './chunk-M3AARGLI.js';
5
5
  import { useOverlayLayer, useCloseOnFocusOut, focusInitial, rovingTabStop, OVERLAY_CLOSE_ATTR, useNonModalDialog, useFocusTrap } from './chunk-NHQCMOAN.js';
@@ -8,8 +8,8 @@ export { CodeBlock, Divider, Link } from './chunk-QJBCZ7BR.js';
8
8
  import { Badge } from './chunk-U2JT37GJ.js';
9
9
  export { Badge } from './chunk-U2JT37GJ.js';
10
10
  import { inferColumnKinds, CardValue } from './chunk-CR2KF73R.js';
11
- import { SplitPaneCtx, usePreferences, TableCardCtx, preferenceActionKey } from './chunk-QNVSMY4R.js';
12
- export { PreferencesContext, preferenceActionKey, usePreferences } from './chunk-QNVSMY4R.js';
11
+ import { SplitPaneCtx, useShellPreferences, TableCardCtx, PREFERENCE_HOUSE_DEFAULTS, preferenceActionKey } from './chunk-TKVTZWBN.js';
12
+ export { PreferencesContext, preferenceActionKey, usePreferences } from './chunk-TKVTZWBN.js';
13
13
  import { useBreakpoint } from './chunk-CRQ6KCRD.js';
14
14
  export { BreakpointWidthProvider, useBreakpoint } from './chunk-CRQ6KCRD.js';
15
15
  import { useTextOverflow, Tooltip, usePosition } from './chunk-IYD6ZDM2.js';
@@ -3859,10 +3859,19 @@ function collectInvalidFields(form) {
3859
3859
  }
3860
3860
  return out;
3861
3861
  }
3862
- function FormWrapper({ onSubmit, validationMode: validationModeProp, children, actions, actionsAlign: actionsAlignProp, focusFirstError = true, errorSummary = true, className, ref }) {
3863
- const preferences = usePreferences();
3862
+ function FormWrapper({ onSubmit, validationMode: validationModeProp, children, actions: actionsProp, actionsAlign: actionsAlignProp, onCancel, cancelLabel = "Cancel", focusFirstError = true, errorSummary = true, className, ref }) {
3863
+ const preferences = useShellPreferences();
3864
3864
  const validationMode = validationModeProp ?? preferences.validationTiming ?? "onSubmit";
3865
3865
  const actionsAlign = actionsAlignProp ?? preferences.formActions?.align ?? "end";
3866
+ const overlayClose = useContext(OverlayCloseCtx);
3867
+ const actions = useMemo(() => {
3868
+ if (!onCancel) return actionsProp;
3869
+ const cancel = /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", onClick: () => (overlayClose ?? onCancel)(), children: cancelLabel }, "gs-form-cancel");
3870
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3871
+ cancel,
3872
+ actionsProp
3873
+ ] });
3874
+ }, [actionsProp, onCancel, overlayClose, cancelLabel]);
3866
3875
  const [errors, setErrors] = useState({});
3867
3876
  const [submitted, setSubmitted] = useState(false);
3868
3877
  const [submitCount, setSubmitCount] = useState(0);
@@ -4201,6 +4210,17 @@ function PanelCheckbox({ checked, indeterminate, onClick, label }) {
4201
4210
  }
4202
4211
  );
4203
4212
  }
4213
+
4214
+ // ../../showcase/src/lib/initials.ts
4215
+ function initialsOf(name) {
4216
+ return name.trim().split(/\s+/).filter(Boolean).slice(0, 2).map((word) => Array.from(word)[0] ?? "").join("").toUpperCase();
4217
+ }
4218
+ function toInitials(value) {
4219
+ const s = value.trim();
4220
+ if (!s) return "";
4221
+ if (!/\s/.test(s) && Array.from(s).length <= 3) return s;
4222
+ return initialsOf(s);
4223
+ }
4204
4224
  var variantColors = {
4205
4225
  success: "bg-[var(--ds-status-success)]",
4206
4226
  warning: "bg-[var(--ds-status-warning)]",
@@ -4309,7 +4329,7 @@ function Avatar({ initials, src, alt, size = "md", status, color = "auto", class
4309
4329
  colorStyles(color, alt ?? initials ?? ""),
4310
4330
  "border-[length:var(--ds-border-width)] border-transparent"
4311
4331
  ),
4312
- children: initials
4332
+ children: initials != null ? toInitials(initials) : null
4313
4333
  }
4314
4334
  );
4315
4335
  if (!status) return avatarElement;
@@ -5243,17 +5263,17 @@ function Table({
5243
5263
  (col) => col.kind ?? inferredKinds.get(col.key),
5244
5264
  [inferredKinds]
5245
5265
  );
5246
- const preferences = usePreferences();
5266
+ const preferences = useShellPreferences();
5247
5267
  const mobileBreakpoint = mobileBreakpointProp ?? preferences.tableToCardsBreakpoint ?? "md";
5248
5268
  const isMobile = useBreakpoint(mobileBreakpoint);
5249
5269
  if (isMobile) {
5250
5270
  if (loading) {
5251
- return /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-center justify-center py-ds-10", className), children: /* @__PURE__ */ jsx(Spinner, { label: "Loading table data" }) });
5271
+ return /* @__PURE__ */ jsx("div", { ref, "data-ds-list": "", className: cn("flex items-center justify-center py-ds-10", className), children: /* @__PURE__ */ jsx(Spinner, { label: "Loading table data" }) });
5252
5272
  }
5253
5273
  if (data.length === 0 && emptyState) {
5254
- return /* @__PURE__ */ jsx("div", { ref, className: cn("py-ds-10 text-center text-sm text-[var(--ds-text-muted)]", className), children: emptyState });
5274
+ return /* @__PURE__ */ jsx("div", { ref, "data-ds-list": "", className: cn("py-ds-10 text-center text-sm text-[var(--ds-text-muted)]", className), children: emptyState });
5255
5275
  }
5256
- return /* @__PURE__ */ jsx(TableCardCtx, { value: true, children: /* @__PURE__ */ jsx("div", { ref, className: cn("flex flex-col gap-ds-3 overflow-y-auto", className), children: sortedWithIndices.map(({ row, originalIdx }, i) => {
5276
+ return /* @__PURE__ */ jsx(TableCardCtx, { value: true, children: /* @__PURE__ */ jsx("div", { ref, "data-ds-list": "", className: cn("flex flex-col gap-ds-3 overflow-y-auto", className), children: sortedWithIndices.map(({ row, originalIdx }, i) => {
5257
5277
  const isSelected = selectedSet.has(originalIdx);
5258
5278
  return /* @__PURE__ */ jsxs(
5259
5279
  "div",
@@ -5291,6 +5311,7 @@ function Table({
5291
5311
  "div",
5292
5312
  {
5293
5313
  ref,
5314
+ "data-ds-list": "",
5294
5315
  className: cn(
5295
5316
  "w-full overflow-x-auto",
5296
5317
  "border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
@@ -7208,7 +7229,7 @@ function renderIcon(icon) {
7208
7229
  return icon;
7209
7230
  }
7210
7231
  function EmptyState({ icon, iconFrame = "circle", title, description, action, variant = "empty", bordered = false, style: styleProp, className }) {
7211
- const preferences = usePreferences();
7232
+ const preferences = useShellPreferences();
7212
7233
  const style = styleProp ?? (preferences.emptyStyle === "text-cta" ? "text" : "illustration");
7213
7234
  const iconNode = style === "text" ? void 0 : icon === void 0 || icon === null ? void 0 : renderIcon(icon);
7214
7235
  return /* @__PURE__ */ jsxs(
@@ -7231,9 +7252,6 @@ function EmptyState({ icon, iconFrame = "circle", title, description, action, va
7231
7252
  }
7232
7253
  );
7233
7254
  }
7234
- function initialsOf(name) {
7235
- return name.trim().split(/\s+/).slice(0, 2).map((w) => w[0] ?? "").join("").toUpperCase();
7236
- }
7237
7255
  function looksLikeUrl(s) {
7238
7256
  return /^(?:https?:|data:|blob:|\/|\.{1,2}\/)/.test(s) || /\.[a-z]{2,5}(?:$|[?#])/i.test(s);
7239
7257
  }
@@ -7289,6 +7307,7 @@ function TableToolbar({
7289
7307
  onClearAll,
7290
7308
  resultCount,
7291
7309
  resultNoun = ["result", "results"],
7310
+ pagination,
7292
7311
  actions,
7293
7312
  size = "sm",
7294
7313
  compactBreakpoint = 680,
@@ -7308,8 +7327,16 @@ function TableToolbar({
7308
7327
  const hasChips = !!activeFilters?.length;
7309
7328
  const inPane = useContext(SplitPaneCtx);
7310
7329
  const searchFills = inPane || !primaryFilter && !filters && !actions;
7311
- return /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: size, children: /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-ds-3 min-w-0", className), "data-table-toolbar": "", children: [
7312
- /* @__PURE__ */ jsxs("div", { ref: rowRef, className: "flex items-center gap-ds-2 flex-wrap", children: [
7330
+ const hasControls = !!(search || primaryFilter || filters || actions);
7331
+ const noun = (n) => n === 1 ? resultNoun[0] : resultNoun[1];
7332
+ const total = resultCount ?? pagination?.totalItems;
7333
+ const grows = !!pagination?.style && pagination.style !== "pagination";
7334
+ const shown = grows ? Math.min(pagination.shown ?? pagination.page * pagination.pageSize, total ?? Infinity) : 0;
7335
+ const paged = total !== void 0 && !!pagination && pagination.pageSize > 0 && total > pagination.pageSize;
7336
+ const countText = total === void 0 ? null : grows ? shown < total ? `Showing ${shown} of ${total} ${noun(total)}` : resultCount !== void 0 ? `${resultCount} ${noun(resultCount)}` : null : paged ? `Showing ${Math.min((pagination.page - 1) * pagination.pageSize + 1, total)}\u2013${Math.min(pagination.page * pagination.pageSize, total)} of ${total} ${noun(total)}` : resultCount !== void 0 ? `${resultCount} ${noun(resultCount)}` : null;
7337
+ if (!hasControls && countText === null && !hasChips) return null;
7338
+ return /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: size, children: /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-ds-3 min-w-0 mb-ds-3 last:mb-0", className), "data-table-toolbar": "", children: [
7339
+ hasControls && /* @__PURE__ */ jsxs("div", { ref: rowRef, className: "flex items-center gap-ds-2 flex-wrap", children: [
7313
7340
  search && /* @__PURE__ */ jsx(
7314
7341
  Input,
7315
7342
  {
@@ -7362,17 +7389,29 @@ function TableToolbar({
7362
7389
  ] })
7363
7390
  ] }),
7364
7391
  filters && open && /* @__PURE__ */ jsx("div", { id: filterRowId, className: "flex items-center gap-ds-3 flex-wrap", children: filters }),
7365
- (resultCount !== void 0 || hasChips) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2 flex-wrap", children: [
7366
- resultCount !== void 0 && /* @__PURE__ */ jsxs("span", { className: "text-xs text-[var(--ds-text-muted)]", "aria-live": "polite", children: [
7367
- resultCount,
7368
- " ",
7369
- resultCount === 1 ? resultNoun[0] : resultNoun[1]
7370
- ] }),
7392
+ (countText !== null || hasChips) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2 flex-wrap", children: [
7393
+ countText !== null && /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--ds-text-muted)]", "aria-live": "polite", "data-result-count": "", children: countText }),
7371
7394
  activeFilters?.map((f) => /* @__PURE__ */ jsx(Tag, { size: "sm", variant: "subtle", onRemove: f.onRemove, children: f.label }, f.id)),
7372
7395
  hasChips && onClearAll && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onClearAll, children: "Clear all" })
7373
7396
  ] })
7374
7397
  ] }) });
7375
7398
  }
7399
+ var ICON_TEXT_OFFSET = "calc((2rem - 1.25rem) / 2)";
7400
+ function Marker({ item, vertical }) {
7401
+ if (item.icon) {
7402
+ return /* @__PURE__ */ jsx("div", { "data-timeline-icon": "", className: "shrink-0 w-8 h-8 flex items-center justify-center", children: item.icon });
7403
+ }
7404
+ return /* @__PURE__ */ jsx(
7405
+ "div",
7406
+ {
7407
+ className: cn(
7408
+ "shrink-0 w-3 h-3 rounded-[var(--ds-radius-full)]",
7409
+ vertical && "mt-ds-1",
7410
+ dotVariant[item.variant ?? "default"]
7411
+ )
7412
+ }
7413
+ );
7414
+ }
7376
7415
  var dotVariant = {
7377
7416
  default: "bg-[var(--ds-accent-primary)] shadow-[0_0_0_3px_var(--ds-accent-primary)]/20",
7378
7417
  success: "bg-[var(--ds-status-success)] shadow-[0_0_0_3px_var(--ds-status-success)]/20",
@@ -7421,15 +7460,7 @@ function HorizontalLayout({ items, minItemWidth, className }) {
7421
7460
  )
7422
7461
  }
7423
7462
  ),
7424
- /* @__PURE__ */ jsx(
7425
- "div",
7426
- {
7427
- className: cn(
7428
- "shrink-0 w-3 h-3 rounded-[var(--ds-radius-full)]",
7429
- dotVariant[item.variant ?? "default"]
7430
- )
7431
- }
7432
- ),
7463
+ /* @__PURE__ */ jsx(Marker, { item, vertical: false }),
7433
7464
  /* @__PURE__ */ jsx(
7434
7465
  "div",
7435
7466
  {
@@ -7451,18 +7482,10 @@ function HorizontalLayout({ items, minItemWidth, className }) {
7451
7482
  function VerticalLayout({ items, className }) {
7452
7483
  return /* @__PURE__ */ jsx("div", { className: cn("relative", className), children: items.map((item, i) => /* @__PURE__ */ jsxs("div", { className: "flex gap-ds-4", children: [
7453
7484
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
7454
- /* @__PURE__ */ jsx(
7455
- "div",
7456
- {
7457
- className: cn(
7458
- "shrink-0 w-3 h-3 rounded-[var(--ds-radius-full)] mt-ds-1",
7459
- dotVariant[item.variant ?? "default"]
7460
- )
7461
- }
7462
- ),
7485
+ /* @__PURE__ */ jsx(Marker, { item, vertical: true }),
7463
7486
  i < items.length - 1 && /* @__PURE__ */ jsx("div", { className: "w-[2px] flex-1 bg-[var(--ds-border-subtle)] my-ds-1" })
7464
7487
  ] }),
7465
- /* @__PURE__ */ jsxs("div", { className: cn("pb-ds-6", i === items.length - 1 && "pb-0"), children: [
7488
+ /* @__PURE__ */ jsxs("div", { className: cn("pb-ds-6 min-w-0", i === items.length - 1 && "pb-0"), style: item.icon ? { paddingTop: ICON_TEXT_OFFSET } : void 0, children: [
7466
7489
  /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: item.title }),
7467
7490
  item.description && /* @__PURE__ */ jsx(ExpandableDescription, { children: item.description }),
7468
7491
  item.timestamp && /* @__PURE__ */ jsx("p", { className: "text-2xs text-[var(--ds-text-muted)] mt-ds-0.5 tabular-nums", children: item.timestamp })
@@ -7479,7 +7502,7 @@ function Timeline({ items, orientation = "vertical", minItemWidth = 200, classNa
7479
7502
  }, [ref]);
7480
7503
  const fits = width === 0 || width >= items.length * minItemWidth;
7481
7504
  const horizontal = orientation === "horizontal" || orientation === "responsive" && fits;
7482
- return /* @__PURE__ */ jsx("div", { ref: setRefs, "data-timeline-orientation": horizontal ? "horizontal" : "vertical", className, children: horizontal ? /* @__PURE__ */ jsx(HorizontalLayout, { items, minItemWidth }) : /* @__PURE__ */ jsx(VerticalLayout, { items }) });
7505
+ return /* @__PURE__ */ jsx("div", { ref: setRefs, "data-ds-list": "", "data-timeline-orientation": horizontal ? "horizontal" : "vertical", className, children: horizontal ? /* @__PURE__ */ jsx(HorizontalLayout, { items, minItemWidth }) : /* @__PURE__ */ jsx(VerticalLayout, { items }) });
7483
7506
  }
7484
7507
  var CollapsibleContext = createContext(null);
7485
7508
  function useCollapsible() {
@@ -8397,16 +8420,18 @@ var TOAST_INSET_VARS = {
8397
8420
  "bottom-right": "--ds-toast-inset-bottom-right",
8398
8421
  "bottom-left": "--ds-toast-inset-bottom-left",
8399
8422
  right: "--ds-toast-inset-right",
8400
- left: "--ds-toast-inset-left"
8423
+ left: "--ds-toast-inset-left",
8424
+ top: "--ds-toast-inset-top"
8401
8425
  };
8402
8426
  var LAUNCHER_INSET_PRIORITY = 1;
8403
8427
  var PANEL_INSET_PRIORITY = 2;
8428
+ var NAVBAR_INSET_PRIORITY = 1;
8404
8429
  var registry = /* @__PURE__ */ new WeakMap();
8405
8430
  var seq = 0;
8406
8431
  function claimsFor(target) {
8407
8432
  let entry = registry.get(target);
8408
8433
  if (!entry) {
8409
- entry = { "bottom-right": [], "bottom-left": [], right: [], left: [] };
8434
+ entry = { "bottom-right": [], "bottom-left": [], right: [], left: [], top: [] };
8410
8435
  registry.set(target, entry);
8411
8436
  }
8412
8437
  return entry;
@@ -8744,6 +8769,7 @@ var StackedList = forwardRef(function StackedList2({
8744
8769
  "ul",
8745
8770
  {
8746
8771
  ref,
8772
+ "data-ds-list": "",
8747
8773
  className: cn(
8748
8774
  divided && "divide-y-[length:var(--ds-border-width)] divide-[var(--ds-border-subtle)]",
8749
8775
  className
@@ -9825,11 +9851,50 @@ function Popover({ open, onOpenChange, trigger, children, side = "bottom", align
9825
9851
  )
9826
9852
  ] });
9827
9853
  }
9828
- function Pagination({ currentPage, totalPages, onPageChange, pageSize: pageSizeProp, pageSizeOptions, onPageSizeChange, className }) {
9854
+ function Pagination(props) {
9855
+ if ((props.mode === "load-more" || props.mode === "infinite-scroll") && props.onLoadMore) return /* @__PURE__ */ jsx(LoadMore, { ...props, onLoadMore: props.onLoadMore, scroll: props.mode === "infinite-scroll" });
9856
+ return /* @__PURE__ */ jsx(PageNumbers, { ...props });
9857
+ }
9858
+ function contentTop(el) {
9859
+ let top = el.getBoundingClientRect().top + window.scrollY;
9860
+ for (let n = el.parentElement; n; n = n.parentElement) top += n.scrollTop;
9861
+ return top;
9862
+ }
9863
+ function LoadMore({ hasMore, onLoadMore, loadMoreLabel, currentPage, scroll, className }) {
9864
+ const marker = useRef(null);
9865
+ const load = useLatest(onLoadMore);
9866
+ const loadedAt = useRef(null);
9867
+ useEffect(() => {
9868
+ const el = marker.current;
9869
+ if (!scroll || !hasMore || !el || typeof IntersectionObserver === "undefined") return;
9870
+ const observer = new IntersectionObserver((entries) => {
9871
+ if (!entries.some((e) => e.isIntersecting)) return;
9872
+ const at = contentTop(el);
9873
+ if (loadedAt.current !== null && Math.abs(at - loadedAt.current) < 1) return;
9874
+ loadedAt.current = at;
9875
+ load.current();
9876
+ }, { rootMargin: "200px 0px" });
9877
+ observer.observe(el);
9878
+ const rearm = () => {
9879
+ loadedAt.current = null;
9880
+ };
9881
+ window.addEventListener("scroll", rearm, { capture: true, passive: true });
9882
+ return () => {
9883
+ observer.disconnect();
9884
+ window.removeEventListener("scroll", rearm, { capture: true });
9885
+ };
9886
+ }, [scroll, hasMore, currentPage, load]);
9887
+ if (!hasMore) return null;
9888
+ return /* @__PURE__ */ jsxs("div", { "data-ds-pager": "", "data-pagination-mode": scroll ? "infinite-scroll" : "load-more", className: cn("flex flex-col items-center", className), children: [
9889
+ scroll && /* @__PURE__ */ jsx("div", { ref: marker, "data-load-more-trigger": "", "aria-hidden": "true", className: "h-px w-full" }),
9890
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onLoadMore, children: loadMoreLabel ?? "Load more" })
9891
+ ] });
9892
+ }
9893
+ function PageNumbers({ currentPage, totalPages, onPageChange, pageSize: pageSizeProp, pageSizeOptions, onPageSizeChange, className }) {
9829
9894
  const pages = buildPageRange(currentPage, totalPages);
9830
- const preferences = usePreferences();
9895
+ const preferences = useShellPreferences();
9831
9896
  const pageSize = pageSizeProp ?? preferences.itemsPerPage;
9832
- return /* @__PURE__ */ jsxs("nav", { "aria-label": "Pagination", className: cn("flex flex-wrap items-center gap-ds-3", className), children: [
9897
+ return /* @__PURE__ */ jsxs("nav", { "aria-label": "Pagination", "data-ds-pager": "", className: cn("flex flex-wrap items-center gap-ds-3", className), children: [
9833
9898
  pageSizeOptions && pageSize != null && onPageSizeChange && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2", children: [
9834
9899
  /* @__PURE__ */ jsx("span", { className: "text-sm text-[var(--ds-text-muted)] whitespace-nowrap", children: "Rows per page" }),
9835
9900
  /* @__PURE__ */ jsx(
@@ -12612,6 +12677,31 @@ var Navbar = forwardRef(function Navbar2({
12612
12677
  ro.observe(header);
12613
12678
  return () => ro.disconnect();
12614
12679
  }, [mobileHidesLinks, links]);
12680
+ const [topInset, setTopInset] = useState(null);
12681
+ const shellEl = appShell?.container ?? null;
12682
+ useLayoutEffect(() => {
12683
+ const header = headerRef.current;
12684
+ if (!shellEl || !header) {
12685
+ setTopInset(null);
12686
+ return;
12687
+ }
12688
+ const measure = () => {
12689
+ const shell = shellEl.getBoundingClientRect();
12690
+ const fillsWindow = shell.top <= 1 && shell.height >= window.innerHeight - 1;
12691
+ const bottom = Math.round(header.getBoundingClientRect().bottom);
12692
+ setTopInset(fillsWindow && bottom > 0 ? `calc(${bottom}px + var(--ds-space-3))` : null);
12693
+ };
12694
+ measure();
12695
+ window.addEventListener("resize", measure);
12696
+ const ro = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
12697
+ ro?.observe(header);
12698
+ ro?.observe(shellEl);
12699
+ return () => {
12700
+ window.removeEventListener("resize", measure);
12701
+ ro?.disconnect();
12702
+ };
12703
+ }, [shellEl]);
12704
+ useCornerInset(topInset ? "top" : null, topInset, NAVBAR_INSET_PRIORITY);
12615
12705
  const hidden = useMemo(() => {
12616
12706
  if (visibleCount === null || links.length === 0) return /* @__PURE__ */ new Set();
12617
12707
  return new Set(links.map((_, i) => i).filter((i) => i >= visibleCount));
@@ -12961,7 +13051,7 @@ function Dialog({ open, onClose: onCloseProp, title, description, children, foot
12961
13051
  }
12962
13052
  ),
12963
13053
  description && /* @__PURE__ */ jsx("p", { id: descriptionId, className: "mt-ds-2 text-sm text-[var(--ds-text-muted)]", children: description }),
12964
- children && /* @__PURE__ */ jsx("div", { className: "mt-ds-4", children })
13054
+ children && /* @__PURE__ */ jsx("div", { className: "mt-ds-4", children: /* @__PURE__ */ jsx(OverlayCloseCtx, { value: onClose, children }) })
12965
13055
  ] })
12966
13056
  ] }) }),
12967
13057
  /* @__PURE__ */ jsx(DiscardConfirm, { open: guard.confirming, onKeep: guard.keep, onDiscard: guard.discard }),
@@ -13838,11 +13928,11 @@ var variantIcons = {
13838
13928
  error: { name: "error", className: "text-[var(--ds-status-error)]" }
13839
13929
  };
13840
13930
  var TOAST_POSITION_CLASSES = {
13841
- "top-right": "top-ds-4 right-[var(--ds-toast-inset-right)]",
13842
- "top-left": "top-ds-4 left-[var(--ds-toast-inset-left)]",
13931
+ "top-right": "top-[var(--ds-toast-inset-top)] right-[var(--ds-toast-inset-right)]",
13932
+ "top-left": "top-[var(--ds-toast-inset-top)] left-[var(--ds-toast-inset-left)]",
13843
13933
  "bottom-right": "bottom-[var(--ds-toast-inset-bottom-right)] right-[var(--ds-toast-inset-right)]",
13844
13934
  "bottom-left": "bottom-[var(--ds-toast-inset-bottom-left)] left-[var(--ds-toast-inset-left)]",
13845
- "top-center": "top-ds-4 left-1/2 -translate-x-1/2",
13935
+ "top-center": "top-[var(--ds-toast-inset-top)] left-1/2 -translate-x-1/2",
13846
13936
  "bottom-center": "bottom-ds-4 left-1/2 -translate-x-1/2"
13847
13937
  };
13848
13938
  function Toast({ variant = "default", message, visible, onDismiss, duration = 5e3, pauseOnHover = false, action, position = "bottom-right", mode, container, inline = false }) {
@@ -14040,9 +14130,70 @@ function ToastProvider({ children, maxVisible = 1, position = "bottom-right", du
14040
14130
  )
14041
14131
  ] });
14042
14132
  }
14133
+ function firstKey(item) {
14134
+ if (item !== null && typeof item === "object") return "id" in item ? item.id : void 0;
14135
+ return item;
14136
+ }
14137
+ function signature(list, resetOn) {
14138
+ let reset = "";
14139
+ try {
14140
+ reset = JSON.stringify(resetOn ?? null);
14141
+ } catch {
14142
+ reset = String(resetOn);
14143
+ }
14144
+ let first = "";
14145
+ try {
14146
+ first = JSON.stringify(firstKey(list[0]) ?? null);
14147
+ } catch {
14148
+ first = "";
14149
+ }
14150
+ return `${list.length}|${first}|${reset}`;
14151
+ }
14152
+ function usePagination(list, options = {}) {
14153
+ const shell = useShellPreferences();
14154
+ const style = options.style ?? shell.paginationStyle ?? PREFERENCE_HOUSE_DEFAULTS.paginationStyle;
14155
+ const [chosenSize, setChosenSize] = useState(null);
14156
+ const pageSize = Math.max(1, Math.floor(chosenSize ?? options.pageSize ?? shell.itemsPerPage ?? PREFERENCE_HOUSE_DEFAULTS.itemsPerPage));
14157
+ const [page, setPageState] = useState(1);
14158
+ const sig = signature(list, options.resetOn);
14159
+ const [seen, setSeen] = useState(sig);
14160
+ if (seen !== sig) {
14161
+ setSeen(sig);
14162
+ if (page !== 1) setPageState(1);
14163
+ }
14164
+ const totalItems = list.length;
14165
+ const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
14166
+ const current = Math.min(Math.max(1, seen !== sig ? 1 : page), totalPages);
14167
+ const grows = style !== "pagination";
14168
+ const start = grows ? 0 : (current - 1) * pageSize;
14169
+ const items = list.slice(start, current * pageSize);
14170
+ const range = items.length === 0 ? [0, 0] : [start + 1, start + items.length];
14171
+ const hasMore = current < totalPages;
14172
+ const setPage = (next) => setPageState(Math.min(Math.max(1, Math.floor(next)), totalPages));
14173
+ const loadMore = () => setPageState((p) => Math.min(p + 1, totalPages));
14174
+ const setPageSize = (size) => {
14175
+ setChosenSize(Math.max(1, Math.floor(size)));
14176
+ setPageState(1);
14177
+ };
14178
+ return {
14179
+ style,
14180
+ items,
14181
+ page: current,
14182
+ pageSize,
14183
+ totalItems,
14184
+ totalPages,
14185
+ range,
14186
+ shown: items.length,
14187
+ hasMore,
14188
+ loadMore,
14189
+ setPage,
14190
+ setPageSize,
14191
+ props: { currentPage: current, totalPages, onPageChange: setPage, pageSize, onPageSizeChange: setPageSize, mode: style, hasMore, onLoadMore: loadMore }
14192
+ };
14193
+ }
14043
14194
  function useDestructiveAction(options) {
14044
14195
  const { action, title, description, confirmLabel, typeToConfirm, onConfirm, onUndo, undoMessage, severity } = options;
14045
- const preferences = usePreferences();
14196
+ const preferences = useShellPreferences();
14046
14197
  const toast = useToastOptional();
14047
14198
  const [open, setOpen] = useState(false);
14048
14199
  const [typed, setTyped] = useState("");
@@ -14248,6 +14399,6 @@ var TextOverflow = forwardRef(function TextOverflow2({
14248
14399
  return /* @__PURE__ */ jsx(Tooltip, { content: resolvedTooltipContent, children: content });
14249
14400
  });
14250
14401
 
14251
- export { Accordion, ActionPanel, ActionPanelGroup, Alert, AsidePanel, Avatar, AvatarGroup, BottomNav, Breadcrumbs, BulkActionBar, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, ChatMessageList, ChatPanel, Checkbox, CheckboxGroup, CheckboxGroupItem, Collapsible, ColorPicker, Combobox, CommandPalette, ContextMenu, CornerPanel, DEFAULT_DATE_RANGE_PRESETS, DataList, DatePicker, DateRangePicker, DescriptionList, Dialog, Dock, Dropdown, DropdownMenu, EmptyState, EntityCell, Field, FileUpload, FormWrapper, HoverCard, InlineFieldError, Input, Kbd, Label, Launcher, MentionInput, MobileHeaderMenu, NavItem, NavMenu, Navbar, NotificationCenter, NumberInput, PageContainer, PageHeader, Pagination, PinInput, Popover, Progress, RadioGroup, Rating, ScrollArea, SectionHeading, SegmentedControl, SettingsLayout, Sidebar, SidebarNav, SliderRange, StackedList, StatsCard, StatusDot, Stepper, Table, TableToolbar, Tabs, Tag, TagInput, TextOverflow, Textarea, TimePicker, Timeline, Toast, ToastProvider, Toggle, Tour, TransferList, TreeView, useContentWidth, useDestructiveAction, useFormContext, useSidebar, useToast, useToastOptional };
14402
+ export { Accordion, ActionPanel, ActionPanelGroup, Alert, AsidePanel, Avatar, AvatarGroup, BottomNav, Breadcrumbs, BulkActionBar, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, ChatMessageList, ChatPanel, Checkbox, CheckboxGroup, CheckboxGroupItem, Collapsible, ColorPicker, Combobox, CommandPalette, ContextMenu, CornerPanel, DEFAULT_DATE_RANGE_PRESETS, DataList, DatePicker, DateRangePicker, DescriptionList, Dialog, Dock, Dropdown, DropdownMenu, EmptyState, EntityCell, Field, FileUpload, FormWrapper, HoverCard, InlineFieldError, Input, Kbd, Label, Launcher, MentionInput, MobileHeaderMenu, NavItem, NavMenu, Navbar, NotificationCenter, NumberInput, PageContainer, PageHeader, Pagination, PinInput, Popover, Progress, RadioGroup, Rating, ScrollArea, SectionHeading, SegmentedControl, SettingsLayout, Sidebar, SidebarNav, SliderRange, StackedList, StatsCard, StatusDot, Stepper, Table, TableToolbar, Tabs, Tag, TagInput, TextOverflow, Textarea, TimePicker, Timeline, Toast, ToastProvider, Toggle, Tour, TransferList, TreeView, useContentWidth, useDestructiveAction, useFormContext, usePagination, useSidebar, useToast, useToastOptional };
14252
14403
  //# sourceMappingURL=index.js.map
14253
14404
  //# sourceMappingURL=index.js.map