@proteos/ui 0.46.0 → 0.48.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.cjs CHANGED
@@ -13,6 +13,7 @@ var reorderWithEdge = require('@atlaskit/pragmatic-drag-and-drop-hitbox/util/reo
13
13
  var reactTable = require('@tanstack/react-table');
14
14
  var reactVirtual = require('@tanstack/react-virtual');
15
15
  var combine = require('@atlaskit/pragmatic-drag-and-drop/combine');
16
+ var thinkingOrbs = require('thinking-orbs');
16
17
  var date = require('@internationalized/date');
17
18
 
18
19
  function Popover(props) {
@@ -1250,7 +1251,8 @@ var CHANNEL_ICONS = {
1250
1251
  "google-meet": lucideReact.Video,
1251
1252
  "teams-meeting": lucideReact.Video,
1252
1253
  "webex-meeting": lucideReact.Video,
1253
- adhoc: lucideReact.AudioLines
1254
+ adhoc: lucideReact.AudioLines,
1255
+ phone: lucideReact.Phone
1254
1256
  };
1255
1257
  function channelIcon(channel) {
1256
1258
  return CHANNEL_ICONS[channel] ?? lucideReact.MessagesSquare;
@@ -1265,7 +1267,14 @@ function Checkbox({ children, className, ...props }) {
1265
1267
  {
1266
1268
  ...props,
1267
1269
  className: (renderProps) => chunkMWAXK66H_cjs.cn(
1268
- "group inline-flex items-center gap-2.5 cursor-pointer",
1270
+ // `relative` so RAC's visually-hidden <input> — which is absolutely
1271
+ // positioned and is the element that actually receives focus — is
1272
+ // laid out against THIS checkbox. Without a positioned ancestor here
1273
+ // it resolves against a far-away container, ends up outside any
1274
+ // scroll clipping, and focusing it makes the browser scroll a
1275
+ // container the user cannot scroll back (the roles permission
1276
+ // matrix, where toggling a row threw the page off-screen).
1277
+ "group relative inline-flex items-center gap-2.5 cursor-pointer",
1269
1278
  "font-sans text-[14px] text-ink-2 select-none",
1270
1279
  "data-[disabled]:opacity-45 data-[disabled]:cursor-not-allowed",
1271
1280
  typeof className === "function" ? className(renderProps) : className
@@ -2614,6 +2623,7 @@ function useInfiniteScrollSentinel({
2614
2623
  return ref;
2615
2624
  }
2616
2625
  var DEFAULT_ROW_HEIGHT = 32;
2626
+ var SELECTION_COLUMN_ID = "__select__";
2617
2627
  function DataTable({
2618
2628
  query,
2619
2629
  columns,
@@ -2638,6 +2648,9 @@ function DataTable({
2638
2648
  extraRows,
2639
2649
  bodyBefore,
2640
2650
  bodyAfter,
2651
+ selectionMode = "none",
2652
+ selectedIds,
2653
+ onSelectionChange,
2641
2654
  columnBorders = false
2642
2655
  }) {
2643
2656
  const rows = react.useMemo(() => {
@@ -2648,19 +2661,112 @@ function DataTable({
2648
2661
  if (startExtras.length === 0 && endExtras.length === 0) return dataRows;
2649
2662
  return [...startExtras, ...dataRows, ...endExtras];
2650
2663
  }, [query.data, extraRows]);
2664
+ const resolveRowId = react.useMemo(
2665
+ () => getRowId ?? ((row, index) => {
2666
+ const r = row;
2667
+ if (typeof r.id === "string" || typeof r.id === "number") return String(r.id);
2668
+ if (typeof r.slug === "string") return r.slug;
2669
+ return String(index);
2670
+ }),
2671
+ [getRowId]
2672
+ );
2673
+ const selectionEnabled = selectionMode === "multiple";
2674
+ const selected = react.useMemo(() => selectedIds ?? /* @__PURE__ */ new Set(), [selectedIds]);
2675
+ const loadedIds = react.useMemo(
2676
+ () => selectionEnabled ? rows.map((row, index) => resolveRowId(row, index)) : [],
2677
+ [selectionEnabled, rows, resolveRowId]
2678
+ );
2679
+ const lastToggledIndexRef = react.useRef(null);
2680
+ const toggleRow = (id, index, isRange) => {
2681
+ if (!onSelectionChange) return;
2682
+ const next = new Set(selected);
2683
+ const anchor = lastToggledIndexRef.current;
2684
+ if (isRange && anchor !== null) {
2685
+ const [from, to] = anchor <= index ? [anchor, index] : [index, anchor];
2686
+ for (let i = from; i <= to; i += 1) {
2687
+ const rangeId = loadedIds[i];
2688
+ if (rangeId !== void 0) next.add(rangeId);
2689
+ }
2690
+ } else if (next.has(id)) {
2691
+ next.delete(id);
2692
+ } else {
2693
+ next.add(id);
2694
+ }
2695
+ lastToggledIndexRef.current = index;
2696
+ onSelectionChange(next);
2697
+ };
2698
+ const loadedSelectedCount = loadedIds.reduce((count, id) => count + (selected.has(id) ? 1 : 0), 0);
2699
+ const allLoadedSelected = loadedIds.length > 0 && loadedSelectedCount === loadedIds.length;
2700
+ const toggleAllLoaded = () => {
2701
+ if (!onSelectionChange) return;
2702
+ const next = new Set(selected);
2703
+ if (allLoadedSelected) {
2704
+ for (const id of loadedIds) next.delete(id);
2705
+ } else {
2706
+ for (const id of loadedIds) next.add(id);
2707
+ }
2708
+ lastToggledIndexRef.current = null;
2709
+ onSelectionChange(next);
2710
+ };
2711
+ const rangeModifierRef = react.useRef(false);
2712
+ const selectionColumn = react.useMemo(
2713
+ () => ({
2714
+ id: SELECTION_COLUMN_ID,
2715
+ size: 36,
2716
+ enableSorting: false,
2717
+ meta: { align: "center", sticky: "left", cellClassName: "px-0 justify-center" },
2718
+ header: () => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex items-center justify-center w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
2719
+ Checkbox,
2720
+ {
2721
+ "aria-label": allLoadedSelected ? "Deselect all rows" : "Select all rows",
2722
+ isSelected: allLoadedSelected,
2723
+ isIndeterminate: loadedSelectedCount > 0 && !allLoadedSelected,
2724
+ isDisabled: loadedIds.length === 0,
2725
+ onChange: toggleAllLoaded
2726
+ }
2727
+ ) }),
2728
+ cell: ({ row }) => (
2729
+ // Stop the click here: selecting a row must never also open it.
2730
+ /* @__PURE__ */ jsxRuntime.jsx(
2731
+ "span",
2732
+ {
2733
+ className: "inline-flex items-center justify-center w-full",
2734
+ onClick: (event) => event.stopPropagation(),
2735
+ onKeyDown: (event) => {
2736
+ event.stopPropagation();
2737
+ rangeModifierRef.current = event.shiftKey;
2738
+ },
2739
+ onPointerDownCapture: (event) => {
2740
+ rangeModifierRef.current = event.shiftKey;
2741
+ },
2742
+ role: "presentation",
2743
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2744
+ Checkbox,
2745
+ {
2746
+ "aria-label": `Select row ${row.index + 1}`,
2747
+ isSelected: selected.has(row.id),
2748
+ onChange: () => toggleRow(row.id, row.index, rangeModifierRef.current)
2749
+ }
2750
+ )
2751
+ }
2752
+ )
2753
+ )
2754
+ }),
2755
+ // biome-ignore lint/correctness/useExhaustiveDependencies: handlers read the latest selection via closure recreated on these inputs
2756
+ [selected, loadedIds, allLoadedSelected, loadedSelectedCount]
2757
+ );
2758
+ const tableColumns = react.useMemo(
2759
+ () => selectionEnabled ? [selectionColumn, ...columns] : columns,
2760
+ [selectionEnabled, selectionColumn, columns]
2761
+ );
2651
2762
  const table = reactTable.useReactTable({
2652
2763
  data: rows,
2653
- columns,
2764
+ columns: tableColumns,
2654
2765
  state: { sorting: sorting ?? [] },
2655
2766
  ...onSortingChange ? { onSortingChange } : {},
2656
2767
  manualSorting: true,
2657
2768
  getCoreRowModel: reactTable.getCoreRowModel(),
2658
- getRowId: getRowId ? (row, index) => getRowId(row, index) : (row, index) => {
2659
- const r = row;
2660
- if (typeof r.id === "string" || typeof r.id === "number") return String(r.id);
2661
- if (typeof r.slug === "string") return r.slug;
2662
- return String(index);
2663
- }
2769
+ getRowId: (row, index) => resolveRowId(row, index)
2664
2770
  });
2665
2771
  const tableRows = table.getRowModel().rows;
2666
2772
  const tableRowCount = tableRows.length;
@@ -2692,8 +2798,8 @@ function DataTable({
2692
2798
  enabled: !!query.hasNextPage
2693
2799
  });
2694
2800
  const totalColumnWidth = react.useMemo(
2695
- () => columns.reduce((sum, c) => sum + (c.size ?? 140), 0),
2696
- [columns]
2801
+ () => tableColumns.reduce((sum, c) => sum + (c.size ?? 140), 0),
2802
+ [tableColumns]
2697
2803
  );
2698
2804
  const columnsRef = react.useRef(columns);
2699
2805
  columnsRef.current = columns;
@@ -5189,6 +5295,24 @@ function NavGroup({ icon, label, children, className, ...props }) {
5189
5295
  ) })
5190
5296
  ] });
5191
5297
  }
5298
+ var SIZE_PX = { xs: 12, sm: 20, md: 40, lg: 64 };
5299
+ var DESIGN = { xs: 20, sm: 20, md: 64, lg: 64 };
5300
+ function Orb({ size = "sm", state = "solving", speed, theme, className, label }) {
5301
+ const px = SIZE_PX[size];
5302
+ const design = DESIGN[size];
5303
+ return /* @__PURE__ */ jsxRuntime.jsx(
5304
+ thinkingOrbs.ThinkingOrb,
5305
+ {
5306
+ state,
5307
+ size: design,
5308
+ ...speed !== void 0 ? { speed } : {},
5309
+ ...theme !== void 0 ? { theme } : {},
5310
+ className: chunkMWAXK66H_cjs.cn("inline-block shrink-0", className),
5311
+ ...px !== design ? { style: { width: px, height: px } } : {},
5312
+ ...label ? { "aria-label": label } : { "aria-hidden": true }
5313
+ }
5314
+ );
5315
+ }
5192
5316
  var progressBarStyles = tailwindVariants.tv({
5193
5317
  slots: {
5194
5318
  track: "relative overflow-hidden rounded-pill bg-surface-2 w-full",
@@ -5323,6 +5447,12 @@ function FieldTypeTag({ children }) {
5323
5447
  return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[10px] uppercase tracking-[0.08em] text-ink-4", children });
5324
5448
  }
5325
5449
 
5450
+ // src/components/record-filter/field-label.ts
5451
+ var FIELD_LABEL_SEPARATOR = " \xB7 ";
5452
+ function joinFieldLabel(...parts) {
5453
+ return parts.filter((part) => !!part && part.length > 0).join(FIELD_LABEL_SEPARATOR);
5454
+ }
5455
+
5326
5456
  // src/components/record-filter/operators.ts
5327
5457
  var OPERATORS = [
5328
5458
  {
@@ -5454,7 +5584,7 @@ function ChipItem({
5454
5584
  if (custom !== void 0) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: custom });
5455
5585
  }
5456
5586
  if (field.type === "enum") {
5457
- const option = field.options?.find((o) => o.value === value);
5587
+ const option = findEnumOption(field, value);
5458
5588
  return /* @__PURE__ */ jsxRuntime.jsx(
5459
5589
  Badge,
5460
5590
  {
@@ -5470,6 +5600,9 @@ function ChipItem({
5470
5600
  function Em({ children }) {
5471
5601
  return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[12px] text-ink-4", children });
5472
5602
  }
5603
+ function findEnumOption(field, value) {
5604
+ return field.options?.find((option) => option.value === value);
5605
+ }
5473
5606
  function formatValue(field, operator, value) {
5474
5607
  const arity = arityOf(operator);
5475
5608
  if (arity === 0) return "";
@@ -5477,13 +5610,16 @@ function formatValue(field, operator, value) {
5477
5610
  const arr = Array.isArray(value) ? value : typeof value === "string" && value.length > 0 ? value.split(",") : [];
5478
5611
  if (arr.length === 0) return "\u2014";
5479
5612
  if (field.type === "enum") {
5480
- const labels = arr.map((v) => field.options?.find((x) => x.value === v)?.label ?? v);
5613
+ const labels = arr.map((v) => findEnumOption(field, v)?.label ?? v);
5481
5614
  return labels.length <= 2 ? labels.join(", ") : `${labels[0]}, ${labels[1]} +${labels.length - 2}`;
5482
5615
  }
5483
5616
  return arr.length <= 2 ? arr.join(", ") : `${arr[0]}, ${arr[1]} +${arr.length - 2}`;
5484
5617
  }
5485
5618
  if (field.type === "boolean") return value === true || value === "true" ? "true" : "false";
5486
5619
  if (value === "" || value == null) return "\u2014";
5620
+ if (field.type === "enum") {
5621
+ return findEnumOption(field, String(value))?.label ?? String(value);
5622
+ }
5487
5623
  if (field.type === "number" || field.type === "integer") {
5488
5624
  const n = Number(value);
5489
5625
  return Number.isFinite(n) ? n.toLocaleString() : String(value);
@@ -7091,7 +7227,7 @@ function Chip2({
7091
7227
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-sans text-[12.5px] text-ink-2", children: [
7092
7228
  field.parentLabel ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ink-4", children: [
7093
7229
  field.parentLabel,
7094
- " / "
7230
+ FIELD_LABEL_SEPARATOR
7095
7231
  ] }) : null,
7096
7232
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ink", children: field.shortLabel })
7097
7233
  ] }),
@@ -7666,6 +7802,7 @@ exports.DraftMessageComposer = DraftMessageComposer;
7666
7802
  exports.DraftMessageReview = DraftMessageReview;
7667
7803
  exports.EmptyState = EmptyState;
7668
7804
  exports.ErrorAnimation = ErrorAnimation;
7805
+ exports.FIELD_LABEL_SEPARATOR = FIELD_LABEL_SEPARATOR;
7669
7806
  exports.FieldCaret = FieldCaret;
7670
7807
  exports.FileField = FileField;
7671
7808
  exports.FileViewer = FileViewer;
@@ -7697,6 +7834,7 @@ exports.NavItem = NavItem;
7697
7834
  exports.NavSection = NavSection;
7698
7835
  exports.OPERATORS = OPERATORS;
7699
7836
  exports.OperatorPicker = OperatorPicker;
7837
+ exports.Orb = Orb;
7700
7838
  exports.PROTECTED_COMBOS = PROTECTED_COMBOS;
7701
7839
  exports.Popover = Popover;
7702
7840
  exports.PopoverContent = PopoverContent;
@@ -7714,6 +7852,7 @@ exports.RecordFilterChips = RecordFilterChips;
7714
7852
  exports.RecordFilterEditor = RecordFilterEditor;
7715
7853
  exports.RenderChipItemProvider = RenderChipItemProvider;
7716
7854
  exports.RenderValueInputProvider = RenderValueInputProvider;
7855
+ exports.SELECTION_COLUMN_ID = SELECTION_COLUMN_ID;
7717
7856
  exports.SegmentedControl = SegmentedControl;
7718
7857
  exports.Select = Select;
7719
7858
  exports.Separator = Separator;
@@ -7771,6 +7910,7 @@ exports.isColumnDragData = isColumnDragData;
7771
7910
  exports.isDraftReviewOutcome = isDraftReviewOutcome;
7772
7911
  exports.isEditableTarget = isEditableTarget;
7773
7912
  exports.isPreviewableImageName = isPreviewableImageName;
7913
+ exports.joinFieldLabel = joinFieldLabel;
7774
7914
  exports.makeActionsColumn = makeActionsColumn;
7775
7915
  exports.messageComposerStyles = messageComposerStyles;
7776
7916
  exports.navItemStyles = navItemStyles;