@camstack/ui-library 1.2.253 → 1.2.255

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.cjs CHANGED
@@ -11215,6 +11215,14 @@ var useBackupListLocations = trpc.backup.listLocations.useQuery;
11215
11215
  var useBackupGetEntries = trpc.backup.getEntries.useQuery;
11216
11216
  /** Generated alias around `trpc.backup.restore.useMutation`. */
11217
11217
  var useBackupRestore = trpc.backup.restore.useMutation;
11218
+ /** Generated alias around `trpc.backup.getEncryption.useQuery`. */
11219
+ var useBackupGetEncryption = trpc.backup.getEncryption.useQuery;
11220
+ /** Generated alias around `trpc.backup.setupEncryption.useMutation`. */
11221
+ var useBackupSetupEncryption = trpc.backup.setupEncryption.useMutation;
11222
+ /** Generated alias around `trpc.backup.disableEncryption.useMutation`. */
11223
+ var useBackupDisableEncryption = trpc.backup.disableEncryption.useMutation;
11224
+ /** Generated alias around `trpc.backup.checkBackupKey.useMutation`. */
11225
+ var useBackupCheckBackupKey = trpc.backup.checkBackupKey.useMutation;
11218
11226
  /** Generated alias around `trpc.backup.delete.useMutation`. */
11219
11227
  var useBackupDelete = trpc.backup.delete.useMutation;
11220
11228
  /** Generated alias around `trpc.backup.listArchives.useQuery`. */
@@ -11835,6 +11843,10 @@ var useKeychainAdminPurgeRetiredKeys = trpc.keychainAdmin.purgeRetiredKeys.useMu
11835
11843
  var useKeychainAdminDownloadRecoveryKey = trpc.keychainAdmin.downloadRecoveryKey.useMutation;
11836
11844
  /** Generated alias around `trpc.keychainAdmin.resetKeychain.useMutation`. */
11837
11845
  var useKeychainAdminResetKeychain = trpc.keychainAdmin.resetKeychain.useMutation;
11846
+ /** Generated alias around `trpc.keychainAdmin.resetReport.useQuery`. */
11847
+ var useKeychainAdminResetReport = trpc.keychainAdmin.resetReport.useQuery;
11848
+ /** Generated alias around `trpc.keychainAdmin.acknowledgeReset.useMutation`. */
11849
+ var useKeychainAdminAcknowledgeReset = trpc.keychainAdmin.acknowledgeReset.useMutation;
11838
11850
  /** Generated alias around `trpc.lawnMowerControl.startMowing.useMutation`. */
11839
11851
  var useLawnMowerControlStartMowing = trpc.lawnMowerControl.startMowing.useMutation;
11840
11852
  /** Generated alias around `trpc.lawnMowerControl.pause.useMutation`. */
@@ -12375,6 +12387,8 @@ var usePipelineAnalyticsGetRetrainExportUrl = trpc.pipelineAnalytics.getRetrainE
12375
12387
  var usePipelineAnalyticsSetRetrainFrameComplete = trpc.pipelineAnalytics.setRetrainFrameComplete.useMutation;
12376
12388
  /** Generated alias around `trpc.pipelineAnalytics.writeRetrainArchive.useMutation`. */
12377
12389
  var usePipelineAnalyticsWriteRetrainArchive = trpc.pipelineAnalytics.writeRetrainArchive.useMutation;
12390
+ /** Generated alias around `trpc.pipelineAnalytics.offerRetrainArchive.useMutation`. */
12391
+ var usePipelineAnalyticsOfferRetrainArchive = trpc.pipelineAnalytics.offerRetrainArchive.useMutation;
12378
12392
  /** Generated alias around `trpc.pipelineAnalytics.previewRetrainDataset.useQuery`. */
12379
12393
  var usePipelineAnalyticsPreviewRetrainDataset = trpc.pipelineAnalytics.previewRetrainDataset.useQuery;
12380
12394
  /** Generated alias around `trpc.pipelineAnalytics.createRetrainDatasetVersion.useMutation`. */
@@ -13159,6 +13173,38 @@ var useTerminalSessionWriteInput = trpc.terminalSession.writeInput.useMutation;
13159
13173
  var useTerminalSessionClose = trpc.terminalSession.close.useMutation;
13160
13174
  /** Generated alias around `trpc.toast.onToast.useSubscription`. */
13161
13175
  var useToastOnToast = trpc.toast.onToast.useSubscription;
13176
+ /** Generated alias around `trpc.training.putDatasetVersion.useMutation`. */
13177
+ var useTrainingPutDatasetVersion = trpc.training.putDatasetVersion.useMutation;
13178
+ /** Generated alias around `trpc.training.getDatasetVersion.useQuery`. */
13179
+ var useTrainingGetDatasetVersion = trpc.training.getDatasetVersion.useQuery;
13180
+ /** Generated alias around `trpc.training.listDatasetVersions.useQuery`. */
13181
+ var useTrainingListDatasetVersions = trpc.training.listDatasetVersions.useQuery;
13182
+ /** Generated alias around `trpc.training.findDatasetVersionIdByName.useQuery`. */
13183
+ var useTrainingFindDatasetVersionIdByName = trpc.training.findDatasetVersionIdByName.useQuery;
13184
+ /** Generated alias around `trpc.training.removeDatasetVersion.useMutation`. */
13185
+ var useTrainingRemoveDatasetVersion = trpc.training.removeDatasetVersion.useMutation;
13186
+ /** Generated alias around `trpc.training.listBaseModels.useQuery`. */
13187
+ var useTrainingListBaseModels = trpc.training.listBaseModels.useQuery;
13188
+ /** Generated alias around `trpc.training.planJob.useQuery`. */
13189
+ var useTrainingPlanJob = trpc.training.planJob.useQuery;
13190
+ /** Generated alias around `trpc.training.startJob.useMutation`. */
13191
+ var useTrainingStartJob = trpc.training.startJob.useMutation;
13192
+ /** Generated alias around `trpc.training.listJobs.useQuery`. */
13193
+ var useTrainingListJobs = trpc.training.listJobs.useQuery;
13194
+ /** Generated alias around `trpc.training.getJob.useQuery`. */
13195
+ var useTrainingGetJob = trpc.training.getJob.useQuery;
13196
+ /** Generated alias around `trpc.training.cancelJob.useMutation`. */
13197
+ var useTrainingCancelJob = trpc.training.cancelJob.useMutation;
13198
+ /** Generated alias around `trpc.training.getJobResult.useQuery`. */
13199
+ var useTrainingGetJobResult = trpc.training.getJobResult.useQuery;
13200
+ /** Generated alias around `trpc.training.registerResult.useMutation`. */
13201
+ var useTrainingRegisterResult = trpc.training.registerResult.useMutation;
13202
+ /** Generated alias around `trpc.training.canaryResult.useMutation`. */
13203
+ var useTrainingCanaryResult = trpc.training.canaryResult.useMutation;
13204
+ /** Generated alias around `trpc.training.rollbackCanary.useMutation`. */
13205
+ var useTrainingRollbackCanary = trpc.training.rollbackCanary.useMutation;
13206
+ /** Generated alias around `trpc.training.discardResult.useMutation`. */
13207
+ var useTrainingDiscardResult = trpc.training.discardResult.useMutation;
13162
13208
  /** Generated alias around `trpc.turnProvider.getTurnServers.useQuery`. */
13163
13209
  var useTurnProviderGetTurnServers = trpc.turnProvider.getTurnServers.useQuery;
13164
13210
  /** Generated alias around `trpc.update.installUpdate.useMutation`. */
@@ -13181,12 +13227,8 @@ var useUserManagementSetUserScopes = trpc.userManagement.setUserScopes.useMutati
13181
13227
  var useUserManagementValidateCredentials = trpc.userManagement.validateCredentials.useMutation;
13182
13228
  /** Generated alias around `trpc.userManagement.listApiKeys.useQuery`. */
13183
13229
  var useUserManagementListApiKeys = trpc.userManagement.listApiKeys.useQuery;
13184
- /** Generated alias around `trpc.userManagement.createApiKey.useMutation`. */
13185
- var useUserManagementCreateApiKey = trpc.userManagement.createApiKey.useMutation;
13186
13230
  /** Generated alias around `trpc.userManagement.revokeApiKey.useMutation`. */
13187
13231
  var useUserManagementRevokeApiKey = trpc.userManagement.revokeApiKey.useMutation;
13188
- /** Generated alias around `trpc.userManagement.validateApiKey.useMutation`. */
13189
- var useUserManagementValidateApiKey = trpc.userManagement.validateApiKey.useMutation;
13190
13232
  /** Generated alias around `trpc.userManagement.createScopedToken.useMutation`. */
13191
13233
  var useUserManagementCreateScopedToken = trpc.userManagement.createScopedToken.useMutation;
13192
13234
  /** Generated alias around `trpc.userManagement.revokeScopedToken.useMutation`. */
@@ -13217,8 +13259,6 @@ var useUserManagementOauthVerifyAccessToken = trpc.userManagement.oauthVerifyAcc
13217
13259
  var useUserManagementListExternalIdentities = trpc.userManagement.listExternalIdentities.useQuery;
13218
13260
  /** Generated alias around `trpc.userManagement.findUserByExternalIdentity.useQuery`. */
13219
13261
  var useUserManagementFindUserByExternalIdentity = trpc.userManagement.findUserByExternalIdentity.useQuery;
13220
- /** Generated alias around `trpc.userManagement.linkExternalIdentity.useMutation`. */
13221
- var useUserManagementLinkExternalIdentity = trpc.userManagement.linkExternalIdentity.useMutation;
13222
13262
  /** Generated alias around `trpc.userManagement.unlinkExternalIdentity.useMutation`. */
13223
13263
  var useUserManagementUnlinkExternalIdentity = trpc.userManagement.unlinkExternalIdentity.useMutation;
13224
13264
  /** Generated alias around `trpc.userManagement.listOauthSessions.useQuery`. */
@@ -14994,13 +15034,12 @@ function usePrompt() {
14994
15034
  return useDialogContext$1().prompt;
14995
15035
  }
14996
15036
  var VARIANT_STYLES$2 = {
14997
- danger: { button: "bg-red-500 hover:bg-red-600 text-white" },
14998
- warning: { button: "bg-orange-500 hover:bg-orange-600 text-white" },
14999
- default: { button: "bg-primary hover:bg-primary/90 text-white" }
15037
+ danger: { button: "bg-danger hover:bg-danger/90 text-primary-foreground" },
15038
+ warning: { button: "bg-warning hover:bg-warning/90 text-primary-foreground" },
15039
+ default: { button: "bg-primary hover:bg-primary/90 text-primary-foreground" }
15000
15040
  };
15001
15041
  var CANCEL_CLASS = "px-3 py-1.5 text-xs font-medium rounded-md border border-border text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors";
15002
15042
  function variantOf(state) {
15003
- if (state.kind === "prompt") return "default";
15004
15043
  return state.options.variant ?? "default";
15005
15044
  }
15006
15045
  /**
@@ -15219,7 +15258,7 @@ function PromptBody({ options, value, error, inputRef, onChange }) {
15219
15258
  const inputId = "camstack-dialog-input";
15220
15259
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
15221
15260
  options.message !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
15222
- className: "mt-2 text-xs text-foreground-subtle leading-relaxed",
15261
+ className: "mt-2 max-h-48 overflow-y-auto text-xs text-foreground-subtle leading-relaxed whitespace-pre-line",
15223
15262
  children: options.message
15224
15263
  }),
15225
15264
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
@@ -15243,7 +15282,7 @@ function PromptBody({ options, value, error, inputRef, onChange }) {
15243
15282
  className: "mt-1 w-full rounded-md border border-border bg-surface px-2 py-1.5 text-xs text-foreground outline-none focus:border-primary"
15244
15283
  }),
15245
15284
  error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
15246
- className: "mt-1.5 text-[11px] text-red-400",
15285
+ className: "mt-1.5 text-[11px] text-danger",
15247
15286
  children: error
15248
15287
  })
15249
15288
  ] });
@@ -35226,6 +35265,147 @@ function resolveTableLayout({ mode, columnCount, isNarrow }) {
35226
35265
  return columnCount >= 4 ? "cards" : "table";
35227
35266
  }
35228
35267
  //#endregion
35268
+ //#region src/composites/data-table-pager.tsx
35269
+ /**
35270
+ * The pager under a paginated {@link DataTable}: the range ("26–50 of 167")
35271
+ * and previous / next. A `<nav>` named after its table, because two paged
35272
+ * tables on one page are otherwise two identical landmarks.
35273
+ *
35274
+ * The range is a polite live region: a screen-reader user who pressed "Next"
35275
+ * hears where they landed without having to hunt for it.
35276
+ */
35277
+ function DataTablePager({ page, labels, onPageChange }) {
35278
+ const atStart = page.page === 0;
35279
+ const atEnd = page.page >= page.pageCount - 1;
35280
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("nav", {
35281
+ "aria-label": labels.navLabel,
35282
+ className: "flex items-center justify-end gap-2 pt-2",
35283
+ children: [
35284
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
35285
+ "aria-live": "polite",
35286
+ className: "text-[11px] tabular-nums text-foreground-subtle",
35287
+ children: labels.range(page.from, page.to, page.total)
35288
+ }),
35289
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
35290
+ type: "button",
35291
+ variant: "outline",
35292
+ size: "sm",
35293
+ icon: ChevronLeft,
35294
+ "aria-label": labels.previous,
35295
+ title: labels.previous,
35296
+ disabled: atStart,
35297
+ onClick: () => onPageChange(page.page - 1)
35298
+ }),
35299
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
35300
+ type: "button",
35301
+ variant: "outline",
35302
+ size: "sm",
35303
+ icon: ChevronRight,
35304
+ "aria-label": labels.next,
35305
+ title: labels.next,
35306
+ disabled: atEnd,
35307
+ onClick: () => onPageChange(page.page + 1)
35308
+ })
35309
+ ]
35310
+ });
35311
+ }
35312
+ //#endregion
35313
+ //#region src/composites/data-table-pagination.ts
35314
+ function paginateRows(rows, page, pageSize) {
35315
+ const size = Math.max(1, Math.floor(pageSize));
35316
+ const total = rows.length;
35317
+ const pageCount = Math.max(1, Math.ceil(total / size));
35318
+ const clamped = Math.min(Math.max(0, Math.floor(page)), pageCount - 1);
35319
+ const start = clamped * size;
35320
+ const pageRows = rows.slice(start, start + size);
35321
+ return {
35322
+ pageRows,
35323
+ page: clamped,
35324
+ pageCount,
35325
+ from: pageRows.length === 0 ? 0 : start + 1,
35326
+ to: start + pageRows.length,
35327
+ total
35328
+ };
35329
+ }
35330
+ var DEFAULT_PAGINATION_LABELS = {
35331
+ navLabel: "Table pages",
35332
+ previous: "Previous page",
35333
+ next: "Next page",
35334
+ range: (from, to, total) => `${from}–${to} of ${total}`
35335
+ };
35336
+ //#endregion
35337
+ //#region src/composites/data-table-selection.tsx
35338
+ /**
35339
+ * Row selection for {@link DataTable}, as a synthetic leading column.
35340
+ *
35341
+ * A column, not a second rendering path: the table and the card layout both
35342
+ * already know how to draw columns, so selection works in both without a
35343
+ * branch of its own (in cards, the unlabelled column lands in the card's
35344
+ * footer strip with the other controls).
35345
+ *
35346
+ * Rules a bulk action relies on — pinned in `data-table-paging-selection.test`:
35347
+ * - the header box acts on the selectable rows of the page ON SCREEN only;
35348
+ * - a row `isSelectable` rejects has no box and is never added;
35349
+ * - keys of rows that are not on screen survive a page-level toggle.
35350
+ */
35351
+ var SELECTION_COLUMN_KEY = "__select";
35352
+ var CHECKBOX = "cursor-pointer align-middle";
35353
+ function PageCheckbox({ checked, indeterminate, disabled, label, onToggle }) {
35354
+ const ref = (0, react$1.useRef)(null);
35355
+ (0, react$1.useEffect)(() => {
35356
+ if (ref.current !== null) ref.current.indeterminate = indeterminate;
35357
+ }, [indeterminate]);
35358
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Checkbox, {
35359
+ ref,
35360
+ "aria-label": label,
35361
+ checked,
35362
+ disabled,
35363
+ onChange: onToggle,
35364
+ className: CHECKBOX
35365
+ });
35366
+ }
35367
+ /** The selection column for the rows currently on screen. */
35368
+ function selectionColumn(selection, pageRows, keyOf) {
35369
+ const selectable = selection.isSelectable ?? (() => true);
35370
+ const pageKeys = pageRows.filter(selectable).map(keyOf);
35371
+ const onPage = pageKeys.filter((k) => selection.selected.has(k)).length;
35372
+ const allOnPage = pageKeys.length > 0 && onPage === pageKeys.length;
35373
+ const togglePage = () => {
35374
+ const next = new Set(selection.selected);
35375
+ for (const key of pageKeys) if (allOnPage) next.delete(key);
35376
+ else next.add(key);
35377
+ selection.onChange(next);
35378
+ };
35379
+ const toggleRow = (key) => {
35380
+ const next = new Set(selection.selected);
35381
+ if (next.has(key)) next.delete(key);
35382
+ else next.add(key);
35383
+ selection.onChange(next);
35384
+ };
35385
+ return {
35386
+ key: SELECTION_COLUMN_KEY,
35387
+ width: "w-8",
35388
+ headerRender: () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageCheckbox, {
35389
+ checked: allOnPage,
35390
+ indeterminate: onPage > 0 && !allOnPage,
35391
+ disabled: pageKeys.length === 0,
35392
+ label: selection.pageLabel,
35393
+ onToggle: togglePage
35394
+ }),
35395
+ render: (row) => {
35396
+ if (!selectable(row)) return null;
35397
+ const key = keyOf(row);
35398
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Checkbox, {
35399
+ "aria-label": selection.rowLabel(row),
35400
+ checked: selection.selected.has(key),
35401
+ onChange: () => toggleRow(key),
35402
+ onClick: (e) => e.stopPropagation(),
35403
+ className: CHECKBOX
35404
+ });
35405
+ }
35406
+ };
35407
+ }
35408
+ //#endregion
35229
35409
  //#region src/composites/setting-row.tsx
35230
35410
  function SettingRow({ label, children, actions, elements = "plain", className, valueClassName }) {
35231
35411
  const LabelTag = elements === "description" ? "dt" : "span";
@@ -35397,9 +35577,19 @@ var ALIGN_CLASS = {
35397
35577
  right: "text-right",
35398
35578
  center: "text-center"
35399
35579
  };
35400
- function DataTable({ columns, rows, rowKey, onRowClick, minWidthPx = 480, emptyMessage, className, bordered = true, rowClassName, mobileMode = "scroll", maxBodyHeight, defaultSort }) {
35580
+ function DataTable({ columns, rows, rowKey, onRowClick, minWidthPx = 480, emptyMessage, className, bordered = true, rowClassName, mobileMode = "scroll", maxBodyHeight, defaultSort, sort: sortProp, onSortChange, pageSize, page: pageProp, onPageChange, paginationLabels = DEFAULT_PAGINATION_LABELS, selection }) {
35401
35581
  const isNarrow = useIsMobile();
35402
- const [sort, setSort] = (0, react$1.useState)(defaultSort ?? null);
35582
+ const [innerSort, setInnerSort] = (0, react$1.useState)(defaultSort ?? null);
35583
+ const [innerPage, setInnerPage] = (0, react$1.useState)(0);
35584
+ const sort = sortProp !== void 0 ? sortProp : innerSort;
35585
+ const changeSort = (next) => {
35586
+ if (sortProp === void 0) setInnerSort(next);
35587
+ onSortChange?.(next);
35588
+ };
35589
+ const changePage = (next) => {
35590
+ if (pageProp === void 0) setInnerPage(next);
35591
+ onPageChange?.(next);
35592
+ };
35403
35593
  const layout = resolveTableLayout({
35404
35594
  mode: mobileMode,
35405
35595
  columnCount: columns.length,
@@ -35414,36 +35604,48 @@ function DataTable({ columns, rows, rowKey, onRowClick, minWidthPx = 480, emptyM
35414
35604
  sortValue
35415
35605
  ]);
35416
35606
  const activeSort = sortedColumn === void 0 ? null : sort;
35607
+ const paged = pageSize === void 0 ? null : paginateRows(displayRows, pageProp ?? innerPage, pageSize);
35608
+ const pageRows = paged === null ? displayRows : paged.pageRows;
35609
+ const pager = paged !== null && paged.pageCount > 1 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTablePager, {
35610
+ page: paged,
35611
+ labels: paginationLabels,
35612
+ onPageChange: changePage
35613
+ }) : null;
35614
+ const keyOf = (row) => String(rowKey ? rowKey(row, rows.indexOf(row)) : rows.indexOf(row));
35615
+ const shownColumns = selection === void 0 ? columns : [selectionColumn(selection, pageRows, keyOf), ...columns];
35417
35616
  if (rows.length === 0 && emptyMessage) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
35418
35617
  className: `rounded-lg ${bordered ? "border border-border" : ""} bg-surface px-3 py-4 text-xs text-foreground-subtle text-center ${className ?? ""}`,
35419
35618
  children: emptyMessage
35420
35619
  });
35421
35620
  if (rows.length === 0) return null;
35422
- if (layout === "cards") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
35423
- className: `space-y-2 ${scrolls ? `${maxBodyHeight} overflow-y-auto` : ""} ${className ?? ""}`,
35424
- children: displayRows.map((row, rowIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTableCard, {
35425
- row,
35426
- rowIndex,
35427
- columns,
35428
- bordered,
35429
- onRowClick,
35430
- rowClassName
35431
- }, rowKey ? rowKey(row, rowIndex) : rowIndex))
35432
- });
35433
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
35621
+ if (layout === "cards") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
35622
+ className,
35623
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
35624
+ className: `space-y-2 ${scrolls ? `${maxBodyHeight} overflow-y-auto` : ""}`,
35625
+ children: pageRows.map((row, rowIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTableCard, {
35626
+ row,
35627
+ rowIndex,
35628
+ columns: shownColumns,
35629
+ bordered,
35630
+ onRowClick,
35631
+ rowClassName
35632
+ }, rowKey ? rowKey(row, rowIndex) : rowIndex))
35633
+ }), pager]
35634
+ });
35635
+ const table = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
35434
35636
  className: [
35435
35637
  "rounded-lg",
35436
35638
  bordered ? "border border-border" : "",
35437
35639
  "bg-surface overflow-x-auto",
35438
35640
  scrolls ? `${maxBodyHeight} overflow-y-auto` : "",
35439
- className ?? ""
35641
+ pager === null ? className ?? "" : ""
35440
35642
  ].filter(Boolean).join(" "),
35441
35643
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
35442
35644
  className: `w-full text-xs ${scrolls ? "border-separate border-spacing-0" : ""}`,
35443
35645
  style: { minWidth: `${minWidthPx}px` },
35444
35646
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", {
35445
35647
  className: "bg-surface",
35446
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", { children: columns.map((col) => {
35648
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", { children: shownColumns.map((col) => {
35447
35649
  const align = col.align ?? "left";
35448
35650
  const nowrap = col.nowrap ?? true;
35449
35651
  const sortable = col.sortValue !== void 0;
@@ -35462,21 +35664,22 @@ function DataTable({ columns, rows, rowKey, onRowClick, minWidthPx = 480, emptyM
35462
35664
  label: col.headerRender ? col.headerRender() : col.header,
35463
35665
  active: isSorted,
35464
35666
  dir: isSorted && activeSort !== null ? activeSort.dir : "asc",
35465
- onSort: () => setSort((prev) => nextTableSort(prev, col.key))
35667
+ onSort: () => changeSort(nextTableSort(sort, col.key))
35466
35668
  }) : col.headerRender ? col.headerRender() : col.header
35467
35669
  }, col.key);
35468
35670
  }) })
35469
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: displayRows.map((row, rowIndex) => {
35671
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: pageRows.map((row, rowIndex) => {
35470
35672
  const key = rowKey ? rowKey(row, rowIndex) : rowIndex;
35471
35673
  const extra = rowClassName?.(row, rowIndex) ?? "";
35472
35674
  const interactive = onRowClick !== void 0;
35473
35675
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", {
35474
35676
  onClick: interactive ? () => onRowClick(row, rowIndex) : void 0,
35475
35677
  className: [interactive ? "cursor-pointer hover:bg-primary/5" : "hover:bg-primary/5", extra].filter(Boolean).join(" "),
35476
- children: columns.map((col) => {
35678
+ children: shownColumns.map((col) => {
35477
35679
  const align = col.align ?? "left";
35478
35680
  const nowrap = col.nowrap ?? true;
35479
35681
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
35682
+ "data-cell": col.key,
35480
35683
  className: [
35481
35684
  "px-3 py-2 text-foreground border-b border-border",
35482
35685
  ALIGN_CLASS[align],
@@ -35489,6 +35692,11 @@ function DataTable({ columns, rows, rowKey, onRowClick, minWidthPx = 480, emptyM
35489
35692
  }) })]
35490
35693
  })
35491
35694
  });
35695
+ if (pager === null) return table;
35696
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
35697
+ className,
35698
+ children: [table, pager]
35699
+ });
35492
35700
  }
35493
35701
  /**
35494
35702
  * One row as a card. Columns that carry a plain-text `header` become labelled
@@ -37749,8 +37957,28 @@ function dataTableFacets(rows, facetValue) {
37749
37957
  count
37750
37958
  })).toSorted((a, b) => b.count - a.count || a.value.localeCompare(b.value));
37751
37959
  }
37960
+ /** One chip row per configured group, each derived like {@link dataTableFacets}. */
37961
+ function dataTableFacetGroups(rows, groups) {
37962
+ return (groups ?? []).map((group) => ({
37963
+ id: group.id,
37964
+ facets: dataTableFacets(rows, group.value)
37965
+ }));
37966
+ }
37752
37967
  function isDataTableFilterActive(state) {
37753
- return state.search.trim() !== "" || state.facets.length > 0;
37968
+ const anyGroup = Object.values(state.groups ?? {}).some((values) => values.length > 0);
37969
+ return state.search.trim() !== "" || state.facets.length > 0 || anyGroup;
37970
+ }
37971
+ /** A new state with `value` added to, or removed from, group `groupId`. */
37972
+ function toggleDataTableGroupFacet(state, groupId, value) {
37973
+ const current = state.groups?.[groupId] ?? [];
37974
+ const next = current.includes(value) ? current.filter((v) => v !== value) : [...current, value];
37975
+ return {
37976
+ ...state,
37977
+ groups: {
37978
+ ...state.groups,
37979
+ [groupId]: next
37980
+ }
37981
+ };
37754
37982
  }
37755
37983
  /** A new state with `value` added to, or removed from, the selected facets. */
37756
37984
  function toggleDataTableFacet(state, value) {
@@ -37770,8 +37998,17 @@ function filterDataTableRows(rows, state, config) {
37770
37998
  const facetValue = config.facetValue;
37771
37999
  const present = new Set(dataTableFacets(rows, facetValue).map((f) => f.value));
37772
38000
  const selected = new Set(state.facets.filter((v) => present.has(v)));
38001
+ const groupGates = (config.facetGroups ?? []).flatMap((group) => {
38002
+ const presentInGroup = new Set(dataTableFacets(rows, group.value).map((f) => f.value));
38003
+ const chosen = new Set((state.groups?.[group.id] ?? []).filter((v) => presentInGroup.has(v)));
38004
+ return chosen.size === 0 ? [] : [{
38005
+ value: group.value,
38006
+ chosen
38007
+ }];
38008
+ });
37773
38009
  return rows.filter((row) => {
37774
38010
  if (selected.size > 0 && facetValue !== void 0 && !selected.has(facetValue(row))) return false;
38011
+ if (groupGates.some((gate) => !gate.chosen.has(gate.value(row)))) return false;
37775
38012
  if (needle !== "" && !config.searchText(row).some((text) => fuzzyMatch(needle, text))) return false;
37776
38013
  return true;
37777
38014
  });
@@ -37790,8 +38027,8 @@ function filterDataTableRows(rows, state, config) {
37790
38027
  */
37791
38028
  var CHIP_ON = "rounded-full border border-primary bg-primary/10 px-2 py-0.5 text-[10px] text-foreground";
37792
38029
  var CHIP_OFF = "rounded-full border border-border px-2 py-0.5 text-[10px] text-foreground-muted hover:bg-surface-hover";
37793
- function DataTableFilterBar({ state, facets, labels, onSearch, onToggleFacet, onClear, facetLabel }) {
37794
- const active = state.search.trim() !== "" || state.facets.length > 0;
38030
+ function DataTableFilterBar({ state, facets, labels, onSearch, onToggleFacet, onClear, facetLabel, groups = [], onToggleGroupFacet }) {
38031
+ const active = isDataTableFilterActive(state);
37795
38032
  const showFacets = facets.length > 1;
37796
38033
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
37797
38034
  className: "flex flex-wrap items-center gap-2",
@@ -37829,6 +38066,32 @@ function DataTableFilterBar({ state, facets, labels, onSearch, onToggleFacet, on
37829
38066
  }, facet.value);
37830
38067
  })
37831
38068
  }),
38069
+ groups.filter((group) => group.facets.length > 1).map((group) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38070
+ role: "group",
38071
+ "aria-label": group.label,
38072
+ className: "flex flex-wrap items-center gap-1",
38073
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38074
+ "aria-hidden": true,
38075
+ className: "text-[10px] uppercase tracking-wide text-foreground-subtle",
38076
+ children: group.label
38077
+ }), group.facets.map((facet) => {
38078
+ const pressed = group.selected.includes(facet.value);
38079
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
38080
+ type: "button",
38081
+ onClick: () => onToggleGroupFacet?.(group.id, facet.value),
38082
+ "aria-pressed": pressed,
38083
+ className: pressed ? CHIP_ON : CHIP_OFF,
38084
+ children: [
38085
+ group.facetLabel ? group.facetLabel(facet.value) : facet.value,
38086
+ " ",
38087
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38088
+ className: "text-foreground-subtle tabular-nums",
38089
+ children: facet.count
38090
+ })
38091
+ ]
38092
+ }, facet.value);
38093
+ })]
38094
+ }, group.id)),
37832
38095
  active && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
37833
38096
  type: "button",
37834
38097
  onClick: onClear,
@@ -37860,22 +38123,37 @@ function useDataTableFilter(rows, config) {
37860
38123
  const toggleFacet = (0, react$1.useCallback)((value) => {
37861
38124
  setState((prev) => toggleDataTableFacet(prev, value));
37862
38125
  }, []);
38126
+ const toggleGroupFacet = (0, react$1.useCallback)((groupId, value) => {
38127
+ setState((prev) => toggleDataTableGroupFacet(prev, groupId, value));
38128
+ }, []);
37863
38129
  const clear = (0, react$1.useCallback)(() => setState(EMPTY_DATA_TABLE_FILTER), []);
37864
- const { searchText, facetValue } = config;
38130
+ const { searchText, facetValue, facetGroups } = config;
38131
+ const facets = (0, react$1.useMemo)(() => dataTableFacets(rows, facetValue), [rows, facetValue]);
37865
38132
  return {
37866
38133
  state,
37867
38134
  setSearch,
37868
38135
  toggleFacet,
38136
+ toggleGroupFacet,
38137
+ groups: (0, react$1.useMemo)(() => dataTableFacetGroups(rows, facetGroups).map((group) => ({
38138
+ ...group,
38139
+ selected: state.groups?.[group.id] ?? []
38140
+ })), [
38141
+ rows,
38142
+ facetGroups,
38143
+ state.groups
38144
+ ]),
37869
38145
  clear,
37870
- facets: (0, react$1.useMemo)(() => dataTableFacets(rows, facetValue), [rows, facetValue]),
38146
+ facets,
37871
38147
  rows: (0, react$1.useMemo)(() => filterDataTableRows(rows, state, {
37872
38148
  searchText,
37873
- facetValue
38149
+ facetValue,
38150
+ facetGroups
37874
38151
  }), [
37875
38152
  rows,
37876
38153
  state,
37877
38154
  searchText,
37878
- facetValue
38155
+ facetValue,
38156
+ facetGroups
37879
38157
  ]),
37880
38158
  active: isDataTableFilterActive(state)
37881
38159
  };
@@ -61803,6 +62081,7 @@ exports.CoverInlineControl = CoverInlineControl;
61803
62081
  exports.CoverPanel = CoverPanel;
61804
62082
  exports.CustomFieldRenderersProvider = CustomFieldRenderersProvider;
61805
62083
  exports.DEFAULT_COLOR = DEFAULT_COLOR;
62084
+ exports.DEFAULT_PAGINATION_LABELS = DEFAULT_PAGINATION_LABELS;
61806
62085
  exports.DEVICE_COLUMNS = DEVICE_COLUMNS;
61807
62086
  exports.DEVICE_EXPORT_PAGE_SIZE_KEY = DEVICE_EXPORT_PAGE_SIZE_KEY;
61808
62087
  exports.DEVICE_LIST_PAGE_SIZE_KEY = DEVICE_LIST_PAGE_SIZE_KEY;
@@ -61814,6 +62093,7 @@ exports.DEVICE_TYPE_META = DEVICE_TYPE_META;
61814
62093
  exports.DISPLAY_ICON_REGISTRY = DISPLAY_ICON_REGISTRY;
61815
62094
  exports.DataTable = DataTable;
61816
62095
  exports.DataTableFilterBar = DataTableFilterBar;
62096
+ exports.DataTablePager = DataTablePager;
61817
62097
  exports.DetectionCanvas = DetectionCanvas;
61818
62098
  exports.DetectionOverlay = DetectionOverlay;
61819
62099
  exports.DetectionResultTree = DetectionResultTree;
@@ -62114,6 +62394,7 @@ exports.createSharedContext = createSharedContext;
62114
62394
  exports.createTheme = require_theme_index.createTheme$1;
62115
62395
  exports.cursorFractionFor = cursorFractionFor;
62116
62396
  exports.darkColors = require_theme_index.darkColors$1;
62397
+ exports.dataTableFacetGroups = dataTableFacetGroups;
62117
62398
  exports.dataTableFacets = dataTableFacets;
62118
62399
  exports.defaultOfField = defaultOfField;
62119
62400
  exports.defaultTheme = require_theme_index.defaultTheme$1;
@@ -62197,6 +62478,7 @@ exports.orphanDeviceLabel = orphanDeviceLabel;
62197
62478
  exports.overrideEntityIdFromLink = overrideEntityIdFromLink;
62198
62479
  exports.pageRows = pageRows;
62199
62480
  exports.pageSizeLabel = pageSizeLabel;
62481
+ exports.paginateRows = paginateRows;
62200
62482
  exports.parentDetailOf = parentDetailOf;
62201
62483
  exports.parseIceCandidate = parseIceCandidate;
62202
62484
  exports.parsePickerGroupBy = parsePickerGroupBy;
@@ -62269,6 +62551,7 @@ exports.tankAlert = tankAlert;
62269
62551
  exports.themeToCss = require_theme_index.themeToCss$1;
62270
62552
  exports.toStationaryOverlayBox = toStationaryOverlayBox;
62271
62553
  exports.toggleDataTableFacet = toggleDataTableFacet;
62554
+ exports.toggleDataTableGroupFacet = toggleDataTableGroupFacet;
62272
62555
  exports.togglePickerDevice = togglePickerDevice;
62273
62556
  exports.togglePickerKey = togglePickerKey;
62274
62557
  exports.trainingRefusalText = trainingRefusalText;
@@ -62361,8 +62644,11 @@ exports.useAutomationControlEnable = useAutomationControlEnable;
62361
62644
  exports.useAutomationControlGetStatus = useAutomationControlGetStatus;
62362
62645
  exports.useAutomationControlTrigger = useAutomationControlTrigger;
62363
62646
  exports.useBackupCancel = useBackupCancel;
62647
+ exports.useBackupCheckBackupKey = useBackupCheckBackupKey;
62364
62648
  exports.useBackupDelete = useBackupDelete;
62365
62649
  exports.useBackupDeleteSchedule = useBackupDeleteSchedule;
62650
+ exports.useBackupDisableEncryption = useBackupDisableEncryption;
62651
+ exports.useBackupGetEncryption = useBackupGetEncryption;
62366
62652
  exports.useBackupGetEntries = useBackupGetEntries;
62367
62653
  exports.useBackupList = useBackupList;
62368
62654
  exports.useBackupListArchives = useBackupListArchives;
@@ -62372,6 +62658,7 @@ exports.useBackupListRuns = useBackupListRuns;
62372
62658
  exports.useBackupListSchedules = useBackupListSchedules;
62373
62659
  exports.useBackupPreviewSchedule = useBackupPreviewSchedule;
62374
62660
  exports.useBackupRestore = useBackupRestore;
62661
+ exports.useBackupSetupEncryption = useBackupSetupEncryption;
62375
62662
  exports.useBackupTrigger = useBackupTrigger;
62376
62663
  exports.useBackupUpsertDestinationPolicy = useBackupUpsertDestinationPolicy;
62377
62664
  exports.useBackupUpsertSchedule = useBackupUpsertSchedule;
@@ -62704,12 +62991,14 @@ exports.useIntercomStartTalkSession = useIntercomStartTalkSession;
62704
62991
  exports.useIntercomStopSession = useIntercomStopSession;
62705
62992
  exports.useIsMidWidth = useIsMidWidth;
62706
62993
  exports.useIsMobile = useIsMobile;
62994
+ exports.useKeychainAdminAcknowledgeReset = useKeychainAdminAcknowledgeReset;
62707
62995
  exports.useKeychainAdminDeleteOrphans = useKeychainAdminDeleteOrphans;
62708
62996
  exports.useKeychainAdminDownloadRecoveryKey = useKeychainAdminDownloadRecoveryKey;
62709
62997
  exports.useKeychainAdminListAudit = useKeychainAdminListAudit;
62710
62998
  exports.useKeychainAdminListSecrets = useKeychainAdminListSecrets;
62711
62999
  exports.useKeychainAdminPurgeRetiredKeys = useKeychainAdminPurgeRetiredKeys;
62712
63000
  exports.useKeychainAdminResetKeychain = useKeychainAdminResetKeychain;
63001
+ exports.useKeychainAdminResetReport = useKeychainAdminResetReport;
62713
63002
  exports.useKeychainAdminReveal = useKeychainAdminReveal;
62714
63003
  exports.useKeychainAdminRotateMasterKey = useKeychainAdminRotateMasterKey;
62715
63004
  exports.useKeychainAdminSetSystemSecret = useKeychainAdminSetSystemSecret;
@@ -62990,6 +63279,7 @@ exports.usePipelineAnalyticsListRetrainStaging = usePipelineAnalyticsListRetrain
62990
63279
  exports.usePipelineAnalyticsListTrackMedia = usePipelineAnalyticsListTrackMedia;
62991
63280
  exports.usePipelineAnalyticsListTrackRelations = usePipelineAnalyticsListTrackRelations;
62992
63281
  exports.usePipelineAnalyticsListTracks = usePipelineAnalyticsListTracks;
63282
+ exports.usePipelineAnalyticsOfferRetrainArchive = usePipelineAnalyticsOfferRetrainArchive;
62993
63283
  exports.usePipelineAnalyticsOwnersWithMedia = usePipelineAnalyticsOwnersWithMedia;
62994
63284
  exports.usePipelineAnalyticsPauseForStorageMigration = usePipelineAnalyticsPauseForStorageMigration;
62995
63285
  exports.usePipelineAnalyticsPreviewRetrainDataset = usePipelineAnalyticsPreviewRetrainDataset;
@@ -63401,19 +63691,33 @@ exports.useTerminalSessionUpdateInstance = useTerminalSessionUpdateInstance;
63401
63691
  exports.useTerminalSessionWriteInput = useTerminalSessionWriteInput;
63402
63692
  exports.useThemeMode = require_theme_index.useThemeMode$1;
63403
63693
  exports.useToastOnToast = useToastOnToast;
63694
+ exports.useTrainingCanaryResult = useTrainingCanaryResult;
63695
+ exports.useTrainingCancelJob = useTrainingCancelJob;
63696
+ exports.useTrainingDiscardResult = useTrainingDiscardResult;
63697
+ exports.useTrainingFindDatasetVersionIdByName = useTrainingFindDatasetVersionIdByName;
63698
+ exports.useTrainingGetDatasetVersion = useTrainingGetDatasetVersion;
63699
+ exports.useTrainingGetJob = useTrainingGetJob;
63700
+ exports.useTrainingGetJobResult = useTrainingGetJobResult;
63701
+ exports.useTrainingListBaseModels = useTrainingListBaseModels;
63702
+ exports.useTrainingListDatasetVersions = useTrainingListDatasetVersions;
63703
+ exports.useTrainingListJobs = useTrainingListJobs;
63704
+ exports.useTrainingPlanJob = useTrainingPlanJob;
63705
+ exports.useTrainingPutDatasetVersion = useTrainingPutDatasetVersion;
63706
+ exports.useTrainingRegisterResult = useTrainingRegisterResult;
63707
+ exports.useTrainingRemoveDatasetVersion = useTrainingRemoveDatasetVersion;
63708
+ exports.useTrainingRollbackCanary = useTrainingRollbackCanary;
63709
+ exports.useTrainingStartJob = useTrainingStartJob;
63404
63710
  exports.useTurnProviderGetTurnServers = useTurnProviderGetTurnServers;
63405
63711
  exports.useUpdateGetStatus = useUpdateGetStatus;
63406
63712
  exports.useUpdateInstallUpdate = useUpdateInstallUpdate;
63407
63713
  exports.useUrlQueryParam = useUrlQueryParam;
63408
63714
  exports.useUserManagementConfirmTotp = useUserManagementConfirmTotp;
63409
- exports.useUserManagementCreateApiKey = useUserManagementCreateApiKey;
63410
63715
  exports.useUserManagementCreateScopedToken = useUserManagementCreateScopedToken;
63411
63716
  exports.useUserManagementCreateUser = useUserManagementCreateUser;
63412
63717
  exports.useUserManagementDeleteUser = useUserManagementDeleteUser;
63413
63718
  exports.useUserManagementDisableTotp = useUserManagementDisableTotp;
63414
63719
  exports.useUserManagementFindUserByExternalIdentity = useUserManagementFindUserByExternalIdentity;
63415
63720
  exports.useUserManagementGetTotpStatus = useUserManagementGetTotpStatus;
63416
- exports.useUserManagementLinkExternalIdentity = useUserManagementLinkExternalIdentity;
63417
63721
  exports.useUserManagementListApiKeys = useUserManagementListApiKeys;
63418
63722
  exports.useUserManagementListExternalIdentities = useUserManagementListExternalIdentities;
63419
63723
  exports.useUserManagementListOauthSessions = useUserManagementListOauthSessions;
@@ -63431,7 +63735,6 @@ exports.useUserManagementSetUserScopes = useUserManagementSetUserScopes;
63431
63735
  exports.useUserManagementSetupTotp = useUserManagementSetupTotp;
63432
63736
  exports.useUserManagementUnlinkExternalIdentity = useUserManagementUnlinkExternalIdentity;
63433
63737
  exports.useUserManagementUpdateUser = useUserManagementUpdateUser;
63434
- exports.useUserManagementValidateApiKey = useUserManagementValidateApiKey;
63435
63738
  exports.useUserManagementValidateCredentials = useUserManagementValidateCredentials;
63436
63739
  exports.useUserManagementValidateScopedToken = useUserManagementValidateScopedToken;
63437
63740
  exports.useUserManagementVerifyTotp = useUserManagementVerifyTotp;