@dxos/react-ui-table 0.3.7-main.ea9e237 → 0.3.7-main.ec7f1fc
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/lib/browser/index.mjs +123 -77
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/ComboboxCell.d.ts +12 -0
- package/dist/types/src/components/ComboboxCell.d.ts.map +1 -0
- package/dist/types/src/components/Table.stories.d.ts +1 -3
- package/dist/types/src/components/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/helpers.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +10 -0
- package/dist/types/src/translations.d.ts.map +1 -0
- package/package.json +10 -9
- package/src/components/ComboboxCell.tsx +97 -0
- package/src/components/Table.stories.tsx +36 -11
- package/src/components/index.ts +1 -0
- package/src/helpers.tsx +6 -49
- package/src/translations.ts +15 -0
|
@@ -520,6 +520,89 @@ var TableFoot = ({ footers, expand, slots, debug, border }) => {
|
|
|
520
520
|
}))));
|
|
521
521
|
};
|
|
522
522
|
|
|
523
|
+
// packages/ui/react-ui-table/src/components/ComboboxCell.tsx
|
|
524
|
+
import { CaretDown as CaretDown2 } from "@phosphor-icons/react";
|
|
525
|
+
import React3, { useCallback, useState as useState3 } from "react";
|
|
526
|
+
import { Popover as Popover2, useTranslation } from "@dxos/react-ui";
|
|
527
|
+
import { PopoverCombobox } from "@dxos/react-ui-searchlist";
|
|
528
|
+
import { descriptionText, getSize as getSize2, mx as mx3, staticPlaceholderText } from "@dxos/react-ui-theme";
|
|
529
|
+
|
|
530
|
+
// packages/ui/react-ui-table/src/translations.ts
|
|
531
|
+
var translationKey = "table";
|
|
532
|
+
var translations_default = [
|
|
533
|
+
{
|
|
534
|
+
"en-US": {
|
|
535
|
+
[translationKey]: {
|
|
536
|
+
"no selection label": "\xA0"
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
];
|
|
541
|
+
|
|
542
|
+
// packages/ui/react-ui-table/src/components/ComboboxCell.tsx
|
|
543
|
+
var initialItems = (model, value) => value ? {
|
|
544
|
+
[model.getId(value)]: {
|
|
545
|
+
label: model.getText(value),
|
|
546
|
+
data: value
|
|
547
|
+
}
|
|
548
|
+
} : {};
|
|
549
|
+
var ComboboxCell = ({ model, value, onValueChange }) => {
|
|
550
|
+
const { t } = useTranslation(translationKey);
|
|
551
|
+
const [items, setItems] = useState3(initialItems(model, value));
|
|
552
|
+
const [loading, setLoading] = useState3(false);
|
|
553
|
+
const [searchInputValue, setSearchInputValue] = useState3("");
|
|
554
|
+
const handleSearchInputValueChange = async (text) => {
|
|
555
|
+
setSearchInputValue(text ?? "");
|
|
556
|
+
setLoading(true);
|
|
557
|
+
const items2 = await model.query(text);
|
|
558
|
+
setItems(items2.reduce((acc, item) => {
|
|
559
|
+
acc[model.getId(item)] = {
|
|
560
|
+
label: model.getText(item),
|
|
561
|
+
data: item
|
|
562
|
+
};
|
|
563
|
+
return acc;
|
|
564
|
+
}, initialItems(model, value)));
|
|
565
|
+
setLoading(false);
|
|
566
|
+
};
|
|
567
|
+
const handleValueChange = useCallback((id) => {
|
|
568
|
+
onValueChange(items[id]?.data);
|
|
569
|
+
}, [
|
|
570
|
+
items,
|
|
571
|
+
onValueChange
|
|
572
|
+
]);
|
|
573
|
+
return /* @__PURE__ */ React3.createElement(PopoverCombobox.Root, {
|
|
574
|
+
placeholder: t("no selection label")
|
|
575
|
+
}, /* @__PURE__ */ React3.createElement(PopoverCombobox.Trigger, {
|
|
576
|
+
variant: "ghost",
|
|
577
|
+
classNames: "is-full"
|
|
578
|
+
}, value ? /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("span", {
|
|
579
|
+
className: mx3("font-normal text-start flex-1 min-is-0 truncate mie-2", !value && staticPlaceholderText)
|
|
580
|
+
}, model.getText(value)), /* @__PURE__ */ React3.createElement(CaretDown2, {
|
|
581
|
+
weight: "bold",
|
|
582
|
+
className: getSize2(3)
|
|
583
|
+
})) : null), /* @__PURE__ */ React3.createElement(PopoverCombobox.Content, {
|
|
584
|
+
shouldFilter: false,
|
|
585
|
+
classNames: "is-[--radix-popover-trigger-width]"
|
|
586
|
+
}, /* @__PURE__ */ React3.createElement(PopoverCombobox.Input, {
|
|
587
|
+
value: searchInputValue,
|
|
588
|
+
onValueChange: handleSearchInputValueChange
|
|
589
|
+
}), /* @__PURE__ */ React3.createElement(PopoverCombobox.List, null, searchInputValue.length < 1 ? /* @__PURE__ */ React3.createElement("p", {
|
|
590
|
+
className: mx3("text-center", descriptionText)
|
|
591
|
+
}, "Start typing to search") : loading ? /* @__PURE__ */ React3.createElement("p", {
|
|
592
|
+
className: mx3("text-center", descriptionText)
|
|
593
|
+
}, "Searching\u2026") : /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(PopoverCombobox.Empty, {
|
|
594
|
+
classNames: [
|
|
595
|
+
"text-center",
|
|
596
|
+
descriptionText
|
|
597
|
+
]
|
|
598
|
+
}, "No results"), Object.entries(items).map(([id, { label }]) => /* @__PURE__ */ React3.createElement(PopoverCombobox.Item, {
|
|
599
|
+
key: id,
|
|
600
|
+
value: id,
|
|
601
|
+
onSelect: handleValueChange,
|
|
602
|
+
classNames: "truncate"
|
|
603
|
+
}, label)))), /* @__PURE__ */ React3.createElement(Popover2.Arrow, null)));
|
|
604
|
+
};
|
|
605
|
+
|
|
523
606
|
// packages/ui/react-ui-table/src/helpers.tsx
|
|
524
607
|
import { useFocusFinders } from "@fluentui/react-tabster";
|
|
525
608
|
import { Check as Check2, ClipboardText, X as X2 } from "@phosphor-icons/react";
|
|
@@ -527,9 +610,9 @@ import { createColumnHelper } from "@tanstack/react-table";
|
|
|
527
610
|
import format from "date-fns/format";
|
|
528
611
|
import formatDistanceToNow from "date-fns/formatDistanceToNow";
|
|
529
612
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
530
|
-
import
|
|
531
|
-
import {
|
|
532
|
-
import { getSize as
|
|
613
|
+
import React4, { useRef as useRef3, useState as useState4 } from "react";
|
|
614
|
+
import { Input as Input2, Tooltip } from "@dxos/react-ui";
|
|
615
|
+
import { getSize as getSize3, mx as mx4 } from "@dxos/react-ui-theme";
|
|
533
616
|
import { stripUndefinedValues } from "@dxos/util";
|
|
534
617
|
var findNextFocusable = (findFirstFocusable, container) => {
|
|
535
618
|
const next = findFirstFocusable(container);
|
|
@@ -549,44 +632,6 @@ var createColumnBuilder = () => ({
|
|
|
549
632
|
var defaults = (options, ...sources) => {
|
|
550
633
|
return stripUndefinedValues(defaultsDeep({}, options, ...sources));
|
|
551
634
|
};
|
|
552
|
-
var CellSelector = ({ model, value: _value, onUpdate }) => {
|
|
553
|
-
const [edit, setEdit] = useState3(false);
|
|
554
|
-
const [value, setValue] = useState3();
|
|
555
|
-
useEffect2(() => setValue(_value ? {
|
|
556
|
-
id: model.getId(_value),
|
|
557
|
-
label: model.getText(_value)
|
|
558
|
-
} : void 0), [
|
|
559
|
-
_value
|
|
560
|
-
]);
|
|
561
|
-
const [items, setItems] = useState3([]);
|
|
562
|
-
const handleUpdate = async (text) => {
|
|
563
|
-
const items2 = await model.query(text);
|
|
564
|
-
setItems(items2.map((item) => ({
|
|
565
|
-
id: model.getId(item),
|
|
566
|
-
label: model.getText(item),
|
|
567
|
-
data: item
|
|
568
|
-
})));
|
|
569
|
-
};
|
|
570
|
-
if (!edit) {
|
|
571
|
-
const text = _value ? model.getText(_value) : void 0;
|
|
572
|
-
return (
|
|
573
|
-
// TODO(burdon): Hack to prevent div from collapsing.
|
|
574
|
-
/* @__PURE__ */ React3.createElement("div", {
|
|
575
|
-
className: mx3("w-full px-2", !text && "opacity-0"),
|
|
576
|
-
onClick: () => setEdit(true)
|
|
577
|
-
}, text ?? "-")
|
|
578
|
-
);
|
|
579
|
-
}
|
|
580
|
-
return /* @__PURE__ */ React3.createElement(ComboBox.Root, {
|
|
581
|
-
items,
|
|
582
|
-
value,
|
|
583
|
-
onChange: (value2) => onUpdate(value2?.data),
|
|
584
|
-
onInputChange: handleUpdate
|
|
585
|
-
}, /* @__PURE__ */ React3.createElement(ComboBox.Input, null), /* @__PURE__ */ React3.createElement(ComboBox.Content, null, items.map((item) => /* @__PURE__ */ React3.createElement(ComboBox.Item, {
|
|
586
|
-
key: item.id,
|
|
587
|
-
item
|
|
588
|
-
}, item.label))));
|
|
589
|
-
};
|
|
590
635
|
var ColumnBuilder = class {
|
|
591
636
|
/**
|
|
592
637
|
* Select value
|
|
@@ -595,18 +640,18 @@ var ColumnBuilder = class {
|
|
|
595
640
|
return defaults(props, {
|
|
596
641
|
minSize: 100,
|
|
597
642
|
header: (column) => {
|
|
598
|
-
return /* @__PURE__ */
|
|
643
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
599
644
|
className: "truncate"
|
|
600
645
|
}, label ?? column.header.id);
|
|
601
646
|
},
|
|
602
|
-
cell: model && onUpdate ? (cell) => /* @__PURE__ */
|
|
647
|
+
cell: model && onUpdate ? (cell) => /* @__PURE__ */ React4.createElement(ComboboxCell, {
|
|
603
648
|
model,
|
|
604
649
|
value: cell.getValue(),
|
|
605
|
-
|
|
650
|
+
onValueChange: (value) => onUpdate?.(cell.row.original, cell.column.id, value)
|
|
606
651
|
}) : (cell) => {
|
|
607
652
|
const value = cell.getValue();
|
|
608
|
-
return /* @__PURE__ */
|
|
609
|
-
className:
|
|
653
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
654
|
+
className: mx4("truncate", className)
|
|
610
655
|
}, value ? model.getText(value) : "");
|
|
611
656
|
}
|
|
612
657
|
});
|
|
@@ -619,13 +664,13 @@ var ColumnBuilder = class {
|
|
|
619
664
|
minSize: 100,
|
|
620
665
|
// TODO(burdon): Default.
|
|
621
666
|
header: (column) => {
|
|
622
|
-
return /* @__PURE__ */
|
|
667
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
623
668
|
className: "truncate"
|
|
624
669
|
}, label ?? column.header.id);
|
|
625
670
|
},
|
|
626
671
|
cell: onUpdate ? (cell) => {
|
|
627
672
|
const initialValue = cell.getValue();
|
|
628
|
-
const [value, setValue] =
|
|
673
|
+
const [value, setValue] = useState4(initialValue);
|
|
629
674
|
const inputRef = useRef3(null);
|
|
630
675
|
const { findFirstFocusable } = useFocusFinders();
|
|
631
676
|
const handleSave = (focusNext = false) => {
|
|
@@ -647,7 +692,7 @@ var ColumnBuilder = class {
|
|
|
647
692
|
const rows = cell.table.getRowModel().flatRows;
|
|
648
693
|
const columns = cell.table.getVisibleFlatColumns();
|
|
649
694
|
const placeholder = cell.row.index === rows.length - 1 && columns[0].id === cell.column.id;
|
|
650
|
-
return /* @__PURE__ */
|
|
695
|
+
return /* @__PURE__ */ React4.createElement(Input2.Root, null, /* @__PURE__ */ React4.createElement(Input2.TextInput, {
|
|
651
696
|
ref: inputRef,
|
|
652
697
|
variant: "subdued",
|
|
653
698
|
placeholder: placeholder ? "Add row..." : void 0,
|
|
@@ -659,8 +704,8 @@ var ColumnBuilder = class {
|
|
|
659
704
|
}));
|
|
660
705
|
} : (cell) => {
|
|
661
706
|
const value = cell.getValue();
|
|
662
|
-
return /* @__PURE__ */
|
|
663
|
-
className:
|
|
707
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
708
|
+
className: mx4("truncate", className)
|
|
664
709
|
}, value);
|
|
665
710
|
}
|
|
666
711
|
});
|
|
@@ -672,12 +717,12 @@ var ColumnBuilder = class {
|
|
|
672
717
|
return defaults(props, {
|
|
673
718
|
size: 100,
|
|
674
719
|
minSize: 100,
|
|
675
|
-
header: (cell) => /* @__PURE__ */
|
|
720
|
+
header: (cell) => /* @__PURE__ */ React4.createElement("div", {
|
|
676
721
|
className: "w-full truncate text-right"
|
|
677
722
|
}, label ?? cell.header.id),
|
|
678
723
|
cell: (cell) => {
|
|
679
724
|
const value = cell.getValue();
|
|
680
|
-
const [text, setText] =
|
|
725
|
+
const [text, setText] = useState4();
|
|
681
726
|
const handleEdit = () => {
|
|
682
727
|
if (onUpdate) {
|
|
683
728
|
setText(value !== void 0 ? String(value) : "");
|
|
@@ -692,9 +737,9 @@ var ColumnBuilder = class {
|
|
|
692
737
|
setText(void 0);
|
|
693
738
|
};
|
|
694
739
|
if (text !== void 0) {
|
|
695
|
-
return /* @__PURE__ */
|
|
696
|
-
className:
|
|
697
|
-
}, /* @__PURE__ */
|
|
740
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
741
|
+
className: mx4("grow text-right font-mono", className)
|
|
742
|
+
}, /* @__PURE__ */ React4.createElement(Input2.Root, null, /* @__PURE__ */ React4.createElement(Input2.TextInput, {
|
|
698
743
|
autoFocus: true,
|
|
699
744
|
value: text,
|
|
700
745
|
classNames: "px-2",
|
|
@@ -703,8 +748,8 @@ var ColumnBuilder = class {
|
|
|
703
748
|
onKeyDown: (event) => event.key === "Escape" && handleCancel() || event.key === "Enter" && handleSave()
|
|
704
749
|
})));
|
|
705
750
|
}
|
|
706
|
-
return /* @__PURE__ */
|
|
707
|
-
className:
|
|
751
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
752
|
+
className: mx4('grow w-full text-right font-mono empty:after:content-["\xA0"]', className),
|
|
708
753
|
onClick: handleEdit
|
|
709
754
|
}, value?.toLocaleString(void 0, {
|
|
710
755
|
minimumFractionDigits: digits ?? 0,
|
|
@@ -721,15 +766,15 @@ var ColumnBuilder = class {
|
|
|
721
766
|
return defaults(props, {
|
|
722
767
|
size: 220,
|
|
723
768
|
minSize: 100,
|
|
724
|
-
header: (cell) => /* @__PURE__ */
|
|
769
|
+
header: (cell) => /* @__PURE__ */ React4.createElement("div", null, label ?? cell.header.id),
|
|
725
770
|
cell: (cell) => {
|
|
726
771
|
const value = cell.getValue();
|
|
727
772
|
try {
|
|
728
773
|
const str = value ? formatSpec ? format(value, formatSpec) : relative ? formatDistanceToNow(value, {
|
|
729
774
|
addSuffix: true
|
|
730
775
|
}) : value.toISOString() : void 0;
|
|
731
|
-
return /* @__PURE__ */
|
|
732
|
-
className:
|
|
776
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
777
|
+
className: mx4("font-mono", className)
|
|
733
778
|
}, str);
|
|
734
779
|
} catch (err) {
|
|
735
780
|
console.log(value);
|
|
@@ -745,25 +790,25 @@ var ColumnBuilder = class {
|
|
|
745
790
|
return defaults(props, {
|
|
746
791
|
size: 86,
|
|
747
792
|
minSize: 86,
|
|
748
|
-
header: (cell) => /* @__PURE__ */
|
|
793
|
+
header: (cell) => /* @__PURE__ */ React4.createElement("div", null, label ?? cell.header.id),
|
|
749
794
|
cell: (cell) => {
|
|
750
795
|
const value = cell.getValue();
|
|
751
796
|
if (!value) {
|
|
752
797
|
return;
|
|
753
798
|
}
|
|
754
|
-
const element = /* @__PURE__ */
|
|
799
|
+
const element = /* @__PURE__ */ React4.createElement("div", {
|
|
755
800
|
className: "font-mono font-thin text-green-500 dark:text-green-300"
|
|
756
801
|
}, value.truncate());
|
|
757
802
|
if (!tooltip) {
|
|
758
803
|
return element;
|
|
759
804
|
}
|
|
760
|
-
return /* @__PURE__ */
|
|
805
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
761
806
|
className: "group inline-flex gap-2 items-center"
|
|
762
|
-
}, /* @__PURE__ */
|
|
807
|
+
}, /* @__PURE__ */ React4.createElement(Tooltip.Provider, null, /* @__PURE__ */ React4.createElement(Tooltip.Root, null, /* @__PURE__ */ React4.createElement(Tooltip.Trigger, {
|
|
763
808
|
asChild: true
|
|
764
|
-
}, element), /* @__PURE__ */
|
|
809
|
+
}, element), /* @__PURE__ */ React4.createElement(Tooltip.Content, {
|
|
765
810
|
side: "right"
|
|
766
|
-
}, /* @__PURE__ */
|
|
811
|
+
}, /* @__PURE__ */ React4.createElement(Tooltip.Arrow, null), /* @__PURE__ */ React4.createElement(ClipboardText, {
|
|
767
812
|
onClick: (ev) => {
|
|
768
813
|
ev.stopPropagation();
|
|
769
814
|
void navigator.clipboard.writeText(value.toHex());
|
|
@@ -779,14 +824,14 @@ var ColumnBuilder = class {
|
|
|
779
824
|
return defaults(props, {
|
|
780
825
|
size: 40,
|
|
781
826
|
minSize: 40,
|
|
782
|
-
header: (column) => /* @__PURE__ */
|
|
827
|
+
header: (column) => /* @__PURE__ */ React4.createElement("div", {
|
|
783
828
|
className: "flex grow justify-center"
|
|
784
829
|
}, label ?? column.header.id),
|
|
785
830
|
cell: (cell) => {
|
|
786
831
|
const value = cell.getValue();
|
|
787
|
-
return /* @__PURE__ */
|
|
832
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
788
833
|
className: "flex grow justify-center"
|
|
789
|
-
}, /* @__PURE__ */
|
|
834
|
+
}, /* @__PURE__ */ React4.createElement(Input2.Root, null, /* @__PURE__ */ React4.createElement(Input2.Checkbox, {
|
|
790
835
|
onClick: (event) => event.stopPropagation(),
|
|
791
836
|
classNames: className,
|
|
792
837
|
disabled: !onUpdate,
|
|
@@ -806,22 +851,22 @@ var ColumnBuilder = class {
|
|
|
806
851
|
const IconOff = off?.Icon ?? X2;
|
|
807
852
|
return defaults(props, {
|
|
808
853
|
size: size ?? 32,
|
|
809
|
-
header: (column) => /* @__PURE__ */
|
|
854
|
+
header: (column) => /* @__PURE__ */ React4.createElement("div", {
|
|
810
855
|
className: "justify-center"
|
|
811
856
|
}, label ?? column.header.id),
|
|
812
857
|
cell: (cell) => {
|
|
813
858
|
const value = cell.getValue();
|
|
814
859
|
if (value) {
|
|
815
|
-
return /* @__PURE__ */
|
|
860
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
816
861
|
className: "flex grow justify-center"
|
|
817
|
-
}, /* @__PURE__ */
|
|
818
|
-
className:
|
|
862
|
+
}, /* @__PURE__ */ React4.createElement(IconOn, {
|
|
863
|
+
className: mx4(getSize3(6), on?.className ?? "text-green-700")
|
|
819
864
|
}));
|
|
820
865
|
} else if (value === false) {
|
|
821
|
-
return /* @__PURE__ */
|
|
866
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
822
867
|
className: "flex grow justify-center"
|
|
823
|
-
}, /* @__PURE__ */
|
|
824
|
-
className:
|
|
868
|
+
}, /* @__PURE__ */ React4.createElement(IconOff, {
|
|
869
|
+
className: mx4(getSize3(6), off?.className ?? "text-red-700")
|
|
825
870
|
}));
|
|
826
871
|
} else {
|
|
827
872
|
return null;
|
|
@@ -834,6 +879,7 @@ export {
|
|
|
834
879
|
ColumnBuilder,
|
|
835
880
|
ColumnMenu,
|
|
836
881
|
ColumnPanel,
|
|
882
|
+
ComboboxCell,
|
|
837
883
|
Table,
|
|
838
884
|
columnTypes,
|
|
839
885
|
createColumnBuilder,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../../src/components/ColumnMenu.tsx", "../../../src/schema.ts", "../../../src/components/Table.tsx", "../../../src/theme.ts", "../../../src/helpers.tsx"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Check, CaretDown, Trash, X } from '@phosphor-icons/react';\nimport { type HeaderContext, type RowData } from '@tanstack/react-table';\nimport React, { type FC, type PropsWithChildren, useRef, useState } from 'react';\n\nimport { Button, DensityProvider, Input, Popover, Select, Separator } from '@dxos/react-ui';\nimport { getSize, mx } from '@dxos/react-ui-theme';\nimport { safeParseInt } from '@dxos/util';\n\nimport { type TableDef, type ColumnProps, columnTypes } from '../schema';\n\nexport type ColumnMenuProps<TData extends RowData, TValue> = {\n context: HeaderContext<TData, TValue>;\n tableDefs: TableDef[];\n tableDef: TableDef;\n column: ColumnProps;\n onUpdate?: (id: string, column: ColumnProps) => void;\n onDelete?: (id: string) => void;\n};\n\nexport const ColumnMenu = <TData extends RowData, TValue>({ column, ...props }: ColumnMenuProps<TData, TValue>) => {\n const title = column.label?.length ? column.label : column.id;\n\n return (\n <div className='flex grow items-center overflow-hidden'>\n <div className='truncate' title={title}>\n {title}\n </div>\n <div className='grow' />\n <div className='flex shrink-0'>\n <ColumnPanel {...props} column={column} />\n </div>\n </div>\n );\n};\n\nconst Section: FC<PropsWithChildren & { className?: string }> = ({ children, className }) => (\n <div role='none' className={mx('p-2', className)}>\n {children}\n </div>\n);\n\nexport const ColumnPanel = <TData extends RowData, TValue>({\n context,\n tableDefs,\n tableDef,\n column,\n onUpdate,\n onDelete,\n}: ColumnMenuProps<TData, TValue>) => {\n const [open, setOpen] = useState(false);\n const [prop, setProp] = useState(column.id);\n const [refTable, setRefTable] = useState(column.refTable);\n const [refProp, setRefProp] = useState(column.refProp);\n const [type, setType] = useState(String(column.type));\n const [label, setLabel] = useState(column.label);\n const [digits, setDigits] = useState(String(column.digits ?? '0'));\n const propRef = useRef<HTMLInputElement>(null);\n\n const handleCancel = () => {\n setProp(column.id);\n setOpen(false);\n };\n\n const handleSave = () => {\n // Check valid.\n if (!prop.length || !prop.match(/^[a-zA-Z_].+/i)) {\n propRef.current?.focus();\n return;\n }\n\n // If already exists then check same type.\n const current = tableDef.columns.find((c) => c.id !== column.id && c.id === prop);\n if (current) {\n // TODO(burdon): Allow multiple columns with different refProps. Ensure correct table prop is updated.\n if (current.type !== 'ref' /* || current.ref !== refTable */) {\n // TODO(burdon): Show error.\n propRef.current?.focus();\n return;\n }\n }\n\n onUpdate?.(prop, {\n id: prop, // TODO(burdon): Make unique.\n prop,\n label,\n type: type as ColumnProps['type'],\n refTable,\n refProp,\n digits: safeParseInt(digits),\n });\n\n setOpen(false);\n };\n\n return (\n <Popover.Root open={open} onOpenChange={(nextOpen) => setOpen(nextOpen)}>\n <Popover.Trigger asChild>\n <Button variant='ghost' classNames='p-0'>\n <CaretDown className={getSize(4)} />\n </Button>\n </Popover.Trigger>\n <Popover.Portal>\n <Popover.Content>\n <Popover.Viewport classNames='w-60'>\n <DensityProvider density='fine'>\n <div className='flex flex-col gap-1'>\n <Section>\n <Input.Root>\n <Input.Label classNames='mbe-1'>Label</Input.Label>\n <Input.TextInput\n placeholder='Column label'\n value={label ?? ''}\n onChange={(event) => setLabel(event.target.value)}\n autoFocus\n />\n </Input.Root>\n <Input.Root>\n <Input.Label classNames='mbe-1 mbs-3'>Property</Input.Label>\n <Input.TextInput\n ref={propRef}\n placeholder='Property key'\n // TODO(burdon): Provide hooks for value normalization, ENTER, ESC, etc.\n value={prop ?? ''}\n onChange={(event) => setProp(event.target.value.replace(/[^\\w_]/g, ''))}\n />\n </Input.Root>\n <Input.Root>\n <Input.Label classNames='mbe-1 mbs-3'>Type</Input.Label>\n <Select.Root value={type} onValueChange={setType}>\n <Select.TriggerButton placeholder='Type' classNames='is-full' />\n <Select.Portal>\n <Select.Content>\n <Select.Viewport>\n {Array.from(columnTypes.entries()).map(([type, label]) => (\n <Select.Option key={type} value={type}>\n {label}\n </Select.Option>\n ))}\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n </Input.Root>\n </Section>\n\n {type === 'number' && (\n <>\n <Section>\n <Input.Root>\n <Input.Label classNames='mbe-1 mbs-3'>Decimal places</Input.Label>\n {/* TODO(burdon): Constrain input to numbers. */}\n <Input.TextInput value={digits ?? ''} onChange={(event) => setDigits(event.target.value)} />\n </Input.Root>\n </Section>\n </>\n )}\n\n {/* TODO(burdon): Selectors on same line. */}\n {type === 'ref' && (\n <>\n <Section>\n <Input.Root>\n <Input.Label classNames='mbe-1 mbs-3'>Table</Input.Label>\n <Select.Root value={refTable} onValueChange={setRefTable}>\n <Select.TriggerButton placeholder='Table' classNames='is-full' />\n <Select.Portal>\n <Select.Content>\n <Select.Viewport>\n {tableDefs\n .filter((t) => t.id !== tableDef.id)\n .map(({ id, name }) => (\n <Select.Option key={id} value={id}>\n {name ?? id}\n </Select.Option>\n ))}\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n </Input.Root>\n\n {refTable && (\n <Input.Root>\n <Input.Label classNames='mbe-1 mbs-3'>Table property</Input.Label>\n <Select.Root value={refProp} onValueChange={setRefProp}>\n <Select.TriggerButton placeholder='Property' classNames='is-full' />\n <Select.Portal>\n <Select.Content>\n <Select.Viewport>\n {tableDefs\n .find((tableDef) => tableDef.id === refTable)\n ?.columns.map(({ id, label }) => (\n <Select.Option key={id} value={id}>\n {label ?? id}\n </Select.Option>\n ))}\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n </Input.Root>\n )}\n </Section>\n </>\n )}\n\n <Separator classNames='mli-2' />\n\n <Section className='space-b-1.5'>\n {/* TODO(burdon): Style as DropdownMenuItem. */}\n <Button variant='primary' classNames='is-full flex gap-2' onClick={handleSave}>\n <span>Save</span>\n <div className='grow' />\n <Check className={getSize(5)} />\n </Button>\n <Button classNames='is-full flex gap-2' onClick={handleCancel}>\n <span>Cancel</span>\n <div className='grow' />\n <X className={getSize(5)} />\n </Button>\n <Button classNames='is-full flex gap-2' onClick={() => onDelete?.(column.id)}>\n <span>Delete</span>\n <div className='grow' />\n <Trash className={getSize(5)} />\n </Button>\n </Section>\n </div>\n </DensityProvider>\n </Popover.Viewport>\n <Popover.Arrow />\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n );\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nexport type TableDef = {\n id: string;\n name?: string; // TODO(burdon): Required?\n columns: ColumnProps[];\n};\n\nexport type ColumnType = 'number' | 'boolean' | 'date' | 'string' | 'ref';\n\nexport const columnTypes = new Map<ColumnType, string>([\n ['string', 'Text'],\n ['boolean', 'Checkbox'],\n ['number', 'Number'],\n ['date', 'Date'],\n ['ref', 'Reference'],\n]);\n\nexport type ColumnProps = {\n id: string;\n prop: string;\n type: ColumnType;\n size?: number;\n label?: string;\n\n // type = number\n digits?: number;\n\n // type = ref\n refTable?: string;\n refProp?: string;\n\n // TODO(burdon): Move to meta.\n fixed?: boolean;\n editable?: boolean;\n resizable?: boolean;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport {\n flexRender,\n getCoreRowModel,\n getGroupedRowModel,\n useReactTable,\n type ColumnSizingInfoState,\n type ColumnSizingState,\n type GroupingState,\n type HeaderGroup,\n type Row,\n type RowData,\n type RowSelectionState,\n type TableState,\n type VisibilityState,\n} from '@tanstack/react-table';\nimport React, { Fragment, useEffect, useRef, useState } from 'react';\n\nimport { debounce } from '@dxos/async';\nimport { groupBorder, inputSurface, mx } from '@dxos/react-ui-theme';\n\nimport { defaultTableSlots, type TableSlots } from '../theme';\nimport { type TableColumnDef, type KeyValue } from '../types';\n\n// TODO(burdon): Sort/filter.\n// TODO(burdon): Drag-and-drop.\n// TODO(burdon): Virtual (e.g., log panel).\n\nexport type TableSelection<TData extends RowData> = {\n // Controlled if undefined (by default).\n select?: 'single' | 'single-toggle' | 'multiple' | 'multiple-toggle' | undefined;\n selected?: TData[];\n onSelectedChange?: (selected: TData[] | undefined) => void;\n};\n\n/**\n * Util to update the selection based on the mode.\n */\nexport const updateSelection = (\n selectionState: RowSelectionState,\n id: string,\n selection: TableSelection<any>['select'],\n): RowSelectionState => {\n switch (selection) {\n case 'single': {\n return {\n [id]: true,\n };\n }\n case 'single-toggle': {\n return selectionState[id]\n ? {}\n : {\n [id]: true,\n };\n }\n case 'multiple': {\n return {\n [id]: true,\n ...selectionState,\n };\n }\n case 'multiple-toggle': {\n if (selectionState[id]) {\n const newSelectionState = { ...selectionState };\n delete newSelectionState[id];\n return newSelectionState;\n } else {\n return {\n [id]: true,\n ...selectionState,\n };\n }\n }\n }\n\n return selectionState;\n};\n\nexport type TableProps<TData extends RowData> = {\n keyAccessor?: KeyValue<TData>;\n data?: TData[];\n columns?: TableColumnDef<TData>[];\n columnVisibility?: VisibilityState;\n onColumnResize?: (state: Record<string, number>) => void;\n grouping?: string[];\n header?: boolean;\n footer?: boolean;\n border?: boolean;\n fullWidth?: boolean;\n pinToBottom?: boolean;\n slots?: TableSlots;\n debug?: boolean;\n} & TableSelection<TData>;\n\nexport const Table = <TData extends RowData>({ slots = defaultTableSlots, ...props }: TableProps<TData>) => {\n const {\n data = [],\n columns = [],\n onColumnResize,\n columnVisibility,\n header = true,\n footer,\n select,\n selected,\n onSelectedChange,\n fullWidth,\n pinToBottom,\n debug,\n } = props;\n\n // Update controlled selection.\n // https://tanstack.com/table/v8/docs/api/features/row-selection\n const [focus, setFocus] = useState<string>();\n const [rowSelection, setRowSelection] = useState<RowSelectionState>({});\n useEffect(() => {\n setRowSelection(\n selected?.reduce((selectionState: RowSelectionState, selected) => {\n const row = table.getRowModel().rows.find((row) => row.original === selected);\n if (row) {\n selectionState[row.id] = true;\n }\n\n return selectionState;\n }, {}) ?? {},\n );\n }, [select, selected]);\n\n // Resizing.\n const [columnSizingInfo, setColumnSizingInfo] = useState<ColumnSizingInfoState>({} as ColumnSizingInfoState);\n const onColumnResizeDebounced = debounce<ColumnSizingState>((info) => onColumnResize?.(info), 500);\n useEffect(() => {\n if (columnSizingInfo.columnSizingStart?.length === 0) {\n onColumnResizeDebounced(table.getState().columnSizing);\n }\n }, [columnSizingInfo]);\n\n const [grouping, setGrouping] = useState<GroupingState>(props.grouping ?? []);\n useEffect(() => setGrouping(props.grouping ?? []), [props.grouping]);\n\n //\n // Update table state.\n // https://tanstack.com/table/v8/docs/api/core/table\n //\n const table = useReactTable({\n data,\n columns,\n defaultColumn: {\n size: 400, // Required in order remove default width.\n maxSize: 800,\n },\n getCoreRowModel: getCoreRowModel(),\n meta: {},\n\n // TODO(burdon): Pagination.\n // TODO(burdon): Sorting.\n // TODO(burdon): Filtering.\n state: {\n columnVisibility,\n columnSizingInfo,\n rowSelection,\n grouping,\n },\n\n // Grouping.\n getGroupedRowModel: getGroupedRowModel(),\n onGroupingChange: setGrouping,\n\n // Selection.\n enableRowSelection: select === 'single' || select === 'single-toggle',\n enableMultiRowSelection: select === 'multiple' || select === 'multiple-toggle',\n onRowSelectionChange: (rows) => {\n setRowSelection(rows);\n },\n\n // Resize columns.\n // TODO(burdon): Drag to re-order columns.\n columnResizeMode: 'onChange',\n enableColumnResizing: true,\n onColumnSizingInfoChange: setColumnSizingInfo,\n\n debugTable: debug,\n });\n\n // TODO(burdon): Add flex if not resizable.\n // Create additional expansion column if all columns have fixed width.\n const expand = false; // columns.map((column) => column.size).filter(Boolean).length === columns?.length;\n\n // Pin scrollbar to bottom.\n const containerRef = usePinToBottom(data, pinToBottom);\n\n const handleSelect = (row: Row<TData>) => {\n if (select) {\n // Uncontrolled.\n setRowSelection((selectionState: RowSelectionState) => {\n const newSelectionState = updateSelection(selectionState, row.id, select);\n if (onSelectedChange) {\n const rows: TData[] = Object.keys(newSelectionState).map((id) => table.getRowModel().rowsById[id].original);\n onSelectedChange(rows);\n }\n\n return newSelectionState;\n });\n } else {\n // Controlled.\n onSelectedChange?.([row.original]);\n }\n };\n\n // TODO(burdon): Use radix ScrollArea.\n // https://www.radix-ui.com/primitives/docs/components/scroll-area\n return (\n <div ref={containerRef} className={mx('grow overflow-auto', slots?.root?.className)}>\n <table\n // Styles:\n // table-fixed: Prevents fixed sized columns from shrinking.\n className={mx(!fullWidth && 'table-fixed', inputSurface, slots?.table?.className)}\n style={{\n width: fullWidth ? '100%' : table.getTotalSize(),\n }}\n >\n {/* Head */}\n <TableHead\n {...props}\n slots={slots}\n header={header}\n state={table.getState()}\n headers={table.getHeaderGroups()}\n />\n\n {/* Rows */}\n {grouping.length === 0 && (\n <TableBody\n {...props}\n slots={slots}\n rowSelection={rowSelection}\n expand={expand}\n focus={focus}\n onFocus={setFocus}\n onSelect={handleSelect}\n rows={table.getRowModel().rows}\n />\n )}\n\n {/* Groups */}\n {grouping.length !== 0 &&\n table.getGroupedRowModel().rows.map((row, i) => {\n return (\n <Fragment key={i}>\n {/* TODO(burdon): Customize group header renderer. */}\n <thead>\n <tr>\n {slots?.margin && <th className={mx(slots?.margin?.className)} />}\n {debug && <th />}\n <th\n // TODO(burdon): Calculate row span.\n colSpan={table.getHeaderGroups()[0].headers.length}\n className={mx('text-left', slots?.group?.className)}\n >\n {table.getState().grouping[0]}[{String(row.getGroupingValue(table.getState().grouping[0]))}]\n </th>\n </tr>\n </thead>\n\n <TableBody\n {...props}\n slots={slots}\n rowSelection={rowSelection}\n expand={expand}\n focus={focus}\n onFocus={setFocus}\n onSelect={handleSelect}\n rows={row.subRows}\n />\n </Fragment>\n );\n })}\n\n {/* Foot */}\n {footer && <TableFoot {...props} slots={slots} footers={table.getFooterGroups()} />}\n </table>\n\n {debug && (\n <pre className='font-mono text-xs text-neutral-500 my-4 p-2 ring'>\n <code>{JSON.stringify(table.getState(), undefined, 2)}</code>\n </pre>\n )}\n </div>\n );\n};\n\n/**\n * Glue to bottom as rows are added.\n */\n// TODO(burdon): Causes scrollbar to be constantly visible.\n// https://css-tricks.com/books/greatest-css-tricks/pin-scrolling-to-bottom\nconst usePinToBottom = <TData extends RowData>(data: TData[], pinToBottom?: boolean) => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [stickyScrolling, setStickyScrolling] = useState(true);\n useEffect(() => {\n const container = containerRef.current;\n if (!pinToBottom || !container) {\n return;\n }\n\n // TODO(burdon): Set when scrolled to bottom and unset when manually scrolled away.\n const handler = () => {\n const bottom = container.scrollHeight - container.scrollTop - container.clientHeight === 0;\n setStickyScrolling(bottom);\n };\n\n container.addEventListener('scroll', handler);\n return () => container.removeEventListener('scroll', handler);\n }, []);\n\n useEffect(() => {\n if (!pinToBottom || !containerRef.current || !stickyScrolling) {\n return;\n }\n\n containerRef.current?.scroll({ top: containerRef.current.scrollHeight });\n }, [data]);\n\n return containerRef;\n};\n\n//\n// Head.\n//\n\ntype TableHeadProps<TData extends RowData> = Partial<TableProps<TData>> & {\n state: TableState;\n headers: HeaderGroup<TData>[];\n expand?: boolean;\n};\n\nconst TableHead = <TData extends RowData>({\n state,\n headers,\n expand,\n header,\n debug,\n fullWidth,\n border,\n slots,\n}: TableHeadProps<TData>) => {\n return (\n <thead className={mx(header ? ['sticky top-0 z-10'] : 'collapse')}>\n {headers.map((headerGroup) => {\n return (\n // Group element to hover resize handles.\n <tr key={headerGroup.id} className='font-light group'>\n {slots?.margin && <th className={mx(slots?.margin?.className)} />}\n\n {/* TODO(burdon): Calc. width. */}\n {debug && (\n <th className='text-left' style={{ width: 32 }}>\n #\n </th>\n )}\n\n {headerGroup.headers.map((header) => {\n return (\n <th\n key={header.id}\n style={{\n // Don't set width if fullWidth and no explicit size.\n width: fullWidth && header.column.columnDef.meta?.expand ? undefined : header.getSize(),\n }}\n // Relative for resize handle.\n // TODO(burdon): Border scrolls with main content.\n // https://stackoverflow.com/questions/50361698/border-style-do-not-work-with-sticky-position-element\n className={mx(\n 'relative text-left',\n border && groupBorder,\n slots?.header?.className,\n header.column.columnDef.meta?.slots?.header?.className,\n )}\n >\n {!header || header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n\n {/*\n * Resize handle.\n * https://codesandbox.io/p/sandbox/github/tanstack/table/tree/main/examples/react/column-sizing\n */}\n {header.column.columnDef.meta?.resizable && (\n <div\n className={mx(\n 'absolute top-0 pl-1 h-full z-[10] w-[7px] -right-[5px]',\n 'cursor-col-resize select-none touch-none opacity-20 hover:opacity-100',\n header.column.getIsResizing() && 'hidden',\n )}\n style={{\n transform: header.column.getIsResizing()\n ? `translateX(${state.columnSizingInfo.deltaOffset}px)`\n : undefined,\n }}\n onMouseDown={header.getResizeHandler()}\n onTouchStart={header.getResizeHandler()}\n >\n <div className='flex group-hover:bg-neutral-700 -ml-[2px] w-[1px] h-full' />\n </div>\n )}\n </th>\n );\n })}\n {expand && <th />}\n {slots?.margin && <th className={mx(slots?.margin?.className)} />}\n </tr>\n );\n })}\n </thead>\n );\n};\n\n//\n// Body.\n//\n\ntype TableBodyProps<TData extends RowData> = Partial<TableProps<TData>> & {\n rows: Row<TData>[];\n rowSelection: RowSelectionState;\n expand?: boolean;\n focus?: string;\n onFocus?: (id?: string) => void;\n onSelect?: (row: Row<TData>) => void;\n};\n\nconst TableBody = <TData extends RowData>({\n keyAccessor,\n rows,\n rowSelection,\n focus,\n onFocus,\n onSelect,\n debug,\n border,\n expand,\n slots,\n}: TableBodyProps<TData>) => {\n return (\n <tbody>\n {rows.map((row) => {\n return (\n <tr\n key={keyAccessor ? keyAccessor(row.original) : row.id}\n onClick={() => onSelect?.(row)}\n role='button' // TODO(burdon): ???\n className={mx(\n 'group',\n rowSelection[row.id] && slots?.selected?.className,\n focus === row.id && slots?.focus?.className,\n slots?.row?.className,\n )}\n >\n {/* TODO(burdon): Dummy button for focus (don't alter geometry). */}\n {slots?.margin && (\n <td className={mx(slots?.margin?.className)}>\n <button\n role='button'\n style={{ width: 1, height: 1 }}\n className='focus:outline-none'\n onFocus={() => onFocus?.(keyAccessor ? keyAccessor(row.original) : row.id)}\n onBlur={() => onFocus?.(undefined)}\n onKeyDown={(event) => {\n // TODO(burdon): Move focus.\n switch (event.key) {\n case 'ArrowUp': {\n break;\n }\n case 'ArrowDown': {\n break;\n }\n }\n }}\n />\n </td>\n )}\n\n {debug && <td>{row.id}</td>}\n\n {row.getVisibleCells().map((cell) => {\n // TODO(burdon): Allow class override from column.\n return (\n <td\n key={cell.id}\n className={mx(\n border && groupBorder,\n slots?.cell?.className,\n cell.column.columnDef.meta?.slots?.cell?.className,\n )}\n >\n {flexRender(cell.column.columnDef.cell, { className: 'px-2', ...cell.getContext() })}\n </td>\n );\n })}\n\n {expand && <td />}\n {slots?.margin && <td className={mx(slots?.margin?.className)} />}\n </tr>\n );\n })}\n </tbody>\n );\n};\n\n//\n// Footer\n//\n\ntype TableFootProps<TData extends RowData> = Partial<TableProps<TData>> & {\n footers: HeaderGroup<TData>[];\n expand?: boolean;\n};\n\nconst TableFoot = <TData extends RowData>({ footers, expand, slots, debug, border }: TableFootProps<TData>) => {\n return (\n <tfoot className={mx('sticky bottom-0 z-[10]', slots?.footer?.className)}>\n {footers.map((footerGroup) => (\n <tr key={footerGroup.id} className='font-thin'>\n {slots?.margin && <th className={mx(slots?.margin?.className)} />}\n {debug && <th />}\n\n {footerGroup.headers.map((footer) => {\n return (\n <th\n key={footer.id}\n className={mx(\n border && groupBorder,\n 'text-left',\n slots?.footer?.className,\n footer.column.columnDef.meta?.slots?.footer?.className,\n )}\n >\n {footer.isPlaceholder ? null : flexRender(footer.column.columnDef.footer, footer.getContext())}\n </th>\n );\n })}\n\n {expand && <th />}\n {slots?.margin && <th className={mx(slots?.margin?.className)} />}\n </tr>\n ))}\n </tfoot>\n );\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { chromeSurface } from '@dxos/react-ui-theme';\n\n// TODO(burdon): Remove nested classNames? Add to theme?\nexport type TableSlots = {\n root?: {\n className?: string | string[];\n };\n table?: {\n className?: string | string[];\n };\n header?: {\n className?: string | string[];\n };\n footer?: {\n className?: string | string[];\n };\n group?: {\n className?: string | string[];\n };\n row?: {\n className?: string | string[];\n };\n cell?: {\n className?: string | string[];\n };\n focus?: {\n className?: string | string[];\n };\n selected?: {\n className?: string | string[];\n };\n margin?: {\n className?: string | string[];\n };\n};\n\n// TODO(burdon): Change to groups.\n/*\nhead: {\n default:\n cell:\n}\nrow: {\n default: '',\n selected: ''\n}\n*/\n\n// TODO(burdon): Scrollbar area.\n// TODO(burdon): Overscroll horizontal (full width).\n\n// TODO(burdon): Integrate with DXOS UI theme (direct dependency -- see react-ui-editor, tailwind.ts).\n// See Link.tsx const { tx } = useThemeContext();\n// Reuse button fragments for hoverColors, selected, primary, etc.\nexport const defaultTableSlots: TableSlots = {\n // TODO(burdon): head/body/table rows.\n header: { className: [chromeSurface, 'px-2 font-light select-none'] },\n footer: { className: [chromeSurface, 'px-2 font-light'] },\n cell: { className: 'px-2' },\n group: { className: 'px-2 font-light text-xs text-left' },\n focus: { className: 'ring ring-primary-600 ring-inset' },\n selected: { className: '!bg-teal-100 dark:!bg-teal-700' },\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { useFocusFinders } from '@fluentui/react-tabster';\nimport { Check, ClipboardText, type Icon, X } from '@phosphor-icons/react';\nimport { createColumnHelper, type ColumnDef, type ColumnMeta, type RowData } from '@tanstack/react-table';\nimport format from 'date-fns/format';\nimport formatDistanceToNow from 'date-fns/formatDistanceToNow';\nimport defaultsDeep from 'lodash.defaultsdeep';\nimport React, { useEffect, useRef, useState } from 'react';\n\nimport { type PublicKey } from '@dxos/keys';\nimport { ComboBox, type ComboBoxItem, Input, Tooltip } from '@dxos/react-ui';\nimport { getSize, mx } from '@dxos/react-ui-theme';\nimport { stripUndefinedValues } from '@dxos/util';\n\n// TODO(burdon): Factor out hack to find next focusable element (extend useFocusFinders)?\nconst findNextFocusable = (\n findFirstFocusable: (container: HTMLElement) => HTMLElement | null | undefined,\n container: HTMLElement,\n): HTMLElement | undefined => {\n const next = findFirstFocusable(container as any);\n if (next) {\n if (next?.tagName === 'INPUT') {\n return next;\n }\n if (container.nextElementSibling) {\n return findNextFocusable(findFirstFocusable, container.nextSibling as any);\n }\n }\n};\n\nexport type ValueUpdater<TData extends RowData, TValue> = (row: TData, id: string, value: TValue) => void;\n\nexport const createColumnBuilder = <TData extends RowData>() => ({\n helper: createColumnHelper<TData>(),\n builder: new ColumnBuilder<TData>(),\n});\n\n/**\n * NOTE: Can use `meta` for custom properties.\n */\nexport type BaseColumnOptions<TData, TValue> = Partial<ColumnDef<TData, TValue>> & {\n meta?: ColumnMeta<TData, TValue>;\n label?: string;\n className?: string;\n onUpdate?: ValueUpdater<TData, TValue | undefined>;\n};\n\n// TODO(burdon): Better abstraction?\nexport type SelectQueryModel<TData extends RowData> = {\n getId(object: TData): string;\n getText(object: TData): string;\n query(text?: string): Promise<TData[]>;\n};\n\nexport type SelectColumnOptions<TData extends RowData> = BaseColumnOptions<TData, any> & {\n model: SelectQueryModel<TData>;\n};\n\nexport type StringColumnOptions<TData extends RowData> = BaseColumnOptions<TData, string> & {};\n\nexport type NumberColumnOptions<TData extends RowData> = BaseColumnOptions<TData, number> & {\n digits?: number;\n};\n\nexport type KeyColumnOptions<TData extends RowData> = BaseColumnOptions<TData, PublicKey> & {\n tooltip?: boolean;\n};\n\nexport type DateColumnOptions<TData extends RowData> = BaseColumnOptions<TData, Date> & {\n format?: string;\n relative?: boolean;\n};\n\nexport type BooleanColumnOptions<TData extends RowData> = BaseColumnOptions<TData, boolean> & {};\n\nexport type IconColumnOptions<TData extends RowData> = BaseColumnOptions<TData, boolean> & {\n on?: {\n Icon?: Icon;\n className?: string;\n };\n off?: {\n Icon?: Icon;\n className?: string;\n };\n};\n\nconst defaults = <TData extends RowData, TValue>(\n options: Partial<ColumnDef<TData, TValue>>,\n ...sources: Partial<ColumnDef<TData, TValue>>[]\n): Partial<ColumnDef<TData, TValue>> => {\n return stripUndefinedValues(defaultsDeep({}, options, ...sources));\n};\n\n/**\n * Lazy cell selector (click to activate).\n */\nconst CellSelector = <TData extends RowData>({\n model,\n value: _value,\n onUpdate,\n}: {\n model: SelectQueryModel<TData>;\n value: TData;\n onUpdate: (value: TData) => void;\n}) => {\n const [edit, setEdit] = useState(false);\n const [value, setValue] = useState<ComboBoxItem>();\n useEffect(() => setValue(_value ? { id: model.getId(_value), label: model.getText(_value) } : undefined), [_value]);\n const [items, setItems] = useState<ComboBoxItem[]>([]);\n const handleUpdate = async (text?: string) => {\n const items = await model.query(text);\n setItems(items.map((item) => ({ id: model.getId(item), label: model.getText(item), data: item })));\n };\n\n if (!edit) {\n const text = _value ? model.getText(_value) : undefined;\n return (\n // TODO(burdon): Hack to prevent div from collapsing.\n <div className={mx('w-full px-2', !text && 'opacity-0')} onClick={() => setEdit(true)}>\n {text ?? '-'}\n </div>\n );\n }\n\n return (\n <ComboBox.Root items={items} value={value} onChange={(value) => onUpdate(value?.data)} onInputChange={handleUpdate}>\n <ComboBox.Input />\n <ComboBox.Content>\n {items.map((item) => (\n <ComboBox.Item key={item.id} item={item}>\n {item.label}\n </ComboBox.Item>\n ))}\n </ComboBox.Content>\n </ComboBox.Root>\n );\n};\n\n/**\n * Util to create column definitions.\n */\nexport class ColumnBuilder<TData extends RowData> {\n /**\n * Select value\n */\n select({ label, className, model, onUpdate, ...props }: SelectColumnOptions<TData>): Partial<ColumnDef<TData, any>> {\n return defaults(props, {\n minSize: 100,\n header: (column) => {\n return <div className={'truncate'}>{label ?? column.header.id}</div>;\n },\n cell:\n model && onUpdate\n ? (cell) => (\n <CellSelector<any>\n model={model}\n value={cell.getValue()}\n onUpdate={(value) => onUpdate?.(cell.row.original, cell.column.id, value)}\n />\n )\n : (cell) => {\n const value = cell.getValue();\n return <div className={mx('truncate', className)}>{value ? model.getText(value) : ''}</div>;\n },\n });\n }\n\n /**\n * String formats.\n */\n string({ label, className, onUpdate, ...props }: StringColumnOptions<TData> = {}): Partial<ColumnDef<TData, string>> {\n return defaults(props, {\n minSize: 100,\n // TODO(burdon): Default.\n header: (column) => {\n return <div className={'truncate'}>{label ?? column.header.id}</div>;\n },\n cell: onUpdate\n ? (cell) => {\n // https://tanstack.com/table/v8/docs/examples/react/editable-data\n const initialValue = cell.getValue();\n const [value, setValue] = useState(initialValue);\n const inputRef = useRef<HTMLInputElement>(null);\n const { findFirstFocusable } = useFocusFinders();\n\n const handleSave = (focusNext = false) => {\n if (value === initialValue) {\n return;\n }\n\n onUpdate?.(cell.row.original, cell.column.id, value);\n\n // TODO(burdon): More generally support keyboard navigation.\n if (focusNext) {\n const rowElement = inputRef.current?.parentElement?.parentElement;\n // TODO(burdon): Hack to wait for next row to render.\n setTimeout(() => {\n const next = findNextFocusable(findFirstFocusable, rowElement as HTMLElement);\n next?.focus();\n });\n }\n };\n\n const handleCancel = () => {\n setValue(initialValue);\n };\n\n // Check if first input column of last row.\n const rows = cell.table.getRowModel().flatRows;\n const columns = cell.table.getVisibleFlatColumns();\n const placeholder = cell.row.index === rows.length - 1 && columns[0].id === cell.column.id;\n\n // TODO(burdon): Don't render inputs unless mouse over (Show ellipsis when div)?\n return (\n <Input.Root>\n <Input.TextInput\n ref={inputRef}\n variant='subdued'\n placeholder={placeholder ? 'Add row...' : undefined}\n classNames={'px-2'}\n value={(value as string) ?? ''}\n onBlur={() => handleSave(false)}\n onChange={(event) => setValue(event.target.value)}\n onKeyDown={(event) =>\n (event.key === 'Enter' && handleSave(true)) || (event.key === 'Escape' && handleCancel())\n }\n />\n </Input.Root>\n );\n }\n : (cell) => {\n const value = cell.getValue();\n return <div className={mx('truncate', className)}>{value}</div>;\n },\n });\n }\n\n /**\n * Number formats.\n */\n number({ label, minSize, className, digits, onUpdate, ...props }: NumberColumnOptions<TData> = {}): Partial<\n ColumnDef<TData, number>\n > {\n return defaults(props, {\n size: 100,\n minSize: 100,\n header: (cell) => <div className='w-full truncate text-right'>{label ?? cell.header.id}</div>,\n cell: (cell) => {\n const value = cell.getValue();\n const [text, setText] = useState<string>();\n\n const handleEdit = () => {\n if (onUpdate) {\n setText(value !== undefined ? String(value) : '');\n }\n };\n\n // TODO(burdon): Property is encoded as float (e.g., 6.1 => 6.099)\n const handleSave = () => {\n const value = text?.trim().length ? Number(text) : NaN;\n onUpdate?.(cell.row.original, cell.column.id, isNaN(value) ? undefined : value);\n setText(undefined);\n };\n\n const handleCancel = () => {\n setText(undefined);\n };\n\n if (text !== undefined) {\n return (\n <div className={mx('grow text-right font-mono', className)}>\n <Input.Root>\n <Input.TextInput\n autoFocus\n value={text}\n classNames={'px-2'}\n onBlur={handleSave}\n onChange={(event) => setText(event.target.value)}\n onKeyDown={(event) =>\n (event.key === 'Escape' && handleCancel()) || (event.key === 'Enter' && handleSave())\n }\n />\n </Input.Root>\n </div>\n );\n }\n\n return (\n <div\n className={mx('grow w-full text-right font-mono empty:after:content-[\" \"]', className)}\n onClick={handleEdit}\n >\n {value?.toLocaleString(undefined, {\n minimumFractionDigits: digits ?? 0,\n maximumFractionDigits: digits ?? 2,\n })}\n </div>\n );\n },\n });\n }\n\n /**\n * Date formats.\n */\n // TODO(burdon): Date picker (pluggable renderers?)\n date({ label, format: formatSpec, relative, className, ...props }: DateColumnOptions<TData> = {}): Partial<\n ColumnDef<TData, Date>\n > {\n return defaults(props, {\n size: 220, // TODO(burdon): Depends on format.\n minSize: 100,\n header: (cell) => <div>{label ?? cell.header.id}</div>,\n cell: (cell) => {\n const value = cell.getValue();\n\n try {\n const str = value\n ? formatSpec\n ? format(value, formatSpec)\n : relative\n ? formatDistanceToNow(value, { addSuffix: true })\n : value.toISOString()\n : undefined;\n\n return <div className={mx('font-mono', className)}>{str}</div>;\n } catch (err) {\n console.log(value);\n return null;\n }\n },\n });\n }\n\n /**\n * PublicKey with tooltip.\n */\n key({ label, tooltip, ...props }: KeyColumnOptions<TData> = {}): Partial<ColumnDef<TData, PublicKey>> {\n return defaults(props, {\n size: 86,\n minSize: 86,\n header: (cell) => <div>{label ?? cell.header.id}</div>,\n cell: (cell) => {\n const value = cell.getValue();\n if (!value) {\n return;\n }\n\n // TODO(burdon): Factor out styles.\n const element = (\n <div className='font-mono font-thin text-green-500 dark:text-green-300'>{value.truncate()}</div>\n );\n if (!tooltip) {\n return element;\n }\n\n return (\n <div className='group inline-flex gap-2 items-center'>\n <Tooltip.Provider>\n <Tooltip.Root>\n <Tooltip.Trigger asChild>{element}</Tooltip.Trigger>\n <Tooltip.Content side='right'>\n <Tooltip.Arrow />\n <ClipboardText\n onClick={(ev) => {\n ev.stopPropagation(); // Prevent select row.\n void navigator.clipboard.writeText(value.toHex());\n }}\n />\n </Tooltip.Content>\n </Tooltip.Root>\n </Tooltip.Provider>\n </div>\n );\n },\n });\n }\n\n /**\n * Checkbox.\n */\n checkbox({ label, className, onUpdate, ...props }: BooleanColumnOptions<TData> = {}): Partial<\n ColumnDef<TData, boolean>\n > {\n return defaults(props, {\n size: 40,\n minSize: 40,\n header: (column) => <div className={'flex grow justify-center'}>{label ?? column.header.id}</div>,\n cell: (cell) => {\n const value = cell.getValue();\n // TODO(burdon): Center.\n return (\n <div className='flex grow justify-center'>\n <Input.Root>\n <Input.Checkbox\n onClick={(event) => event.stopPropagation()}\n classNames={className}\n disabled={!onUpdate}\n checked={!!value}\n onCheckedChange={(value) => {\n onUpdate?.(cell.row.original, cell.column.id, !!value);\n }}\n />\n </Input.Root>\n </div>\n );\n },\n });\n }\n\n /**\n * Icon based on boolean value.\n */\n icon({ label, size, on, off, ...props }: IconColumnOptions<TData> = {}): Partial<ColumnDef<TData, boolean>> {\n const IconOn = on?.Icon ?? Check;\n const IconOff = off?.Icon ?? X;\n return defaults(props, {\n size: size ?? 32,\n header: (column) => <div className={'justify-center'}>{label ?? column.header.id}</div>,\n cell: (cell) => {\n const value = cell.getValue();\n if (value) {\n return (\n <div className='flex grow justify-center'>\n <IconOn className={mx(getSize(6), on?.className ?? 'text-green-700')} />\n </div>\n );\n } else if (value === false) {\n return (\n <div className='flex grow justify-center'>\n <IconOff className={mx(getSize(6), off?.className ?? 'text-red-700')} />\n </div>\n );\n } else {\n return null;\n }\n },\n });\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["Check", "CaretDown", "Trash", "X", "React", "useRef", "useState", "Button", "DensityProvider", "Input", "Popover", "Select", "Separator", "getSize", "mx", "safeParseInt", "columnTypes", "Map", "ColumnMenu", "column", "props", "title", "label", "length", "id", "div", "className", "ColumnPanel", "Section", "children", "role", "mx", "context", "tableDefs", "tableDef", "onUpdate", "onDelete", "open", "setOpen", "useState", "prop", "setProp", "refTable", "setRefTable", "refProp", "setRefProp", "type", "setType", "String", "setLabel", "digits", "setDigits", "propRef", "useRef", "handleCancel", "handleSave", "match", "current", "focus", "columns", "find", "c", "safeParseInt", "Popover", "Root", "onOpenChange", "nextOpen", "Trigger", "asChild", "Button", "variant", "classNames", "CaretDown", "getSize", "Portal", "Content", "Viewport", "DensityProvider", "density", "Input", "Label", "TextInput", "placeholder", "value", "onChange", "event", "target", "autoFocus", "ref", "replace", "Select", "onValueChange", "TriggerButton", "Array", "from", "columnTypes", "entries", "map", "Option", "key", "filter", "t", "name", "Separator", "onClick", "span", "Check", "X", "Trash", "Arrow", "flexRender", "getCoreRowModel", "getGroupedRowModel", "useReactTable", "React", "Fragment", "useEffect", "useRef", "useState", "debounce", "groupBorder", "inputSurface", "mx", "chromeSurface", "defaultTableSlots", "header", "className", "chromeSurface", "footer", "cell", "group", "focus", "selected", "updateSelection", "selectionState", "id", "selection", "newSelectionState", "Table", "slots", "defaultTableSlots", "props", "data", "columns", "onColumnResize", "columnVisibility", "header", "footer", "select", "selected", "onSelectedChange", "fullWidth", "pinToBottom", "debug", "focus", "setFocus", "useState", "rowSelection", "setRowSelection", "useEffect", "reduce", "row", "table", "getRowModel", "rows", "find", "original", "columnSizingInfo", "setColumnSizingInfo", "onColumnResizeDebounced", "debounce", "info", "columnSizingStart", "length", "getState", "columnSizing", "grouping", "setGrouping", "useReactTable", "defaultColumn", "size", "maxSize", "getCoreRowModel", "meta", "state", "getGroupedRowModel", "onGroupingChange", "enableRowSelection", "enableMultiRowSelection", "onRowSelectionChange", "columnResizeMode", "enableColumnResizing", "onColumnSizingInfoChange", "debugTable", "expand", "containerRef", "usePinToBottom", "handleSelect", "Object", "keys", "map", "rowsById", "React", "div", "ref", "className", "mx", "root", "inputSurface", "style", "width", "getTotalSize", "TableHead", "headers", "getHeaderGroups", "TableBody", "onFocus", "onSelect", "i", "Fragment", "key", "thead", "tr", "margin", "th", "colSpan", "group", "String", "getGroupingValue", "subRows", "TableFoot", "footers", "getFooterGroups", "pre", "code", "JSON", "stringify", "undefined", "useRef", "stickyScrolling", "setStickyScrolling", "container", "current", "handler", "bottom", "scrollHeight", "scrollTop", "clientHeight", "addEventListener", "removeEventListener", "scroll", "top", "border", "headerGroup", "column", "columnDef", "getSize", "groupBorder", "isPlaceholder", "flexRender", "getContext", "resizable", "getIsResizing", "transform", "deltaOffset", "onMouseDown", "getResizeHandler", "onTouchStart", "keyAccessor", "tbody", "onClick", "role", "td", "button", "height", "onBlur", "onKeyDown", "event", "getVisibleCells", "cell", "tfoot", "footerGroup", "
|
|
3
|
+
"sources": ["../../../src/components/ColumnMenu.tsx", "../../../src/schema.ts", "../../../src/components/Table.tsx", "../../../src/theme.ts", "../../../src/components/ComboboxCell.tsx", "../../../src/translations.ts", "../../../src/helpers.tsx"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Check, CaretDown, Trash, X } from '@phosphor-icons/react';\nimport { type HeaderContext, type RowData } from '@tanstack/react-table';\nimport React, { type FC, type PropsWithChildren, useRef, useState } from 'react';\n\nimport { Button, DensityProvider, Input, Popover, Select, Separator } from '@dxos/react-ui';\nimport { getSize, mx } from '@dxos/react-ui-theme';\nimport { safeParseInt } from '@dxos/util';\n\nimport { type TableDef, type ColumnProps, columnTypes } from '../schema';\n\nexport type ColumnMenuProps<TData extends RowData, TValue> = {\n context: HeaderContext<TData, TValue>;\n tableDefs: TableDef[];\n tableDef: TableDef;\n column: ColumnProps;\n onUpdate?: (id: string, column: ColumnProps) => void;\n onDelete?: (id: string) => void;\n};\n\nexport const ColumnMenu = <TData extends RowData, TValue>({ column, ...props }: ColumnMenuProps<TData, TValue>) => {\n const title = column.label?.length ? column.label : column.id;\n\n return (\n <div className='flex grow items-center overflow-hidden'>\n <div className='truncate' title={title}>\n {title}\n </div>\n <div className='grow' />\n <div className='flex shrink-0'>\n <ColumnPanel {...props} column={column} />\n </div>\n </div>\n );\n};\n\nconst Section: FC<PropsWithChildren & { className?: string }> = ({ children, className }) => (\n <div role='none' className={mx('p-2', className)}>\n {children}\n </div>\n);\n\nexport const ColumnPanel = <TData extends RowData, TValue>({\n context,\n tableDefs,\n tableDef,\n column,\n onUpdate,\n onDelete,\n}: ColumnMenuProps<TData, TValue>) => {\n const [open, setOpen] = useState(false);\n const [prop, setProp] = useState(column.id);\n const [refTable, setRefTable] = useState(column.refTable);\n const [refProp, setRefProp] = useState(column.refProp);\n const [type, setType] = useState(String(column.type));\n const [label, setLabel] = useState(column.label);\n const [digits, setDigits] = useState(String(column.digits ?? '0'));\n const propRef = useRef<HTMLInputElement>(null);\n\n const handleCancel = () => {\n setProp(column.id);\n setOpen(false);\n };\n\n const handleSave = () => {\n // Check valid.\n if (!prop.length || !prop.match(/^[a-zA-Z_].+/i)) {\n propRef.current?.focus();\n return;\n }\n\n // If already exists then check same type.\n const current = tableDef.columns.find((c) => c.id !== column.id && c.id === prop);\n if (current) {\n // TODO(burdon): Allow multiple columns with different refProps. Ensure correct table prop is updated.\n if (current.type !== 'ref' /* || current.ref !== refTable */) {\n // TODO(burdon): Show error.\n propRef.current?.focus();\n return;\n }\n }\n\n onUpdate?.(prop, {\n id: prop, // TODO(burdon): Make unique.\n prop,\n label,\n type: type as ColumnProps['type'],\n refTable,\n refProp,\n digits: safeParseInt(digits),\n });\n\n setOpen(false);\n };\n\n return (\n <Popover.Root open={open} onOpenChange={(nextOpen) => setOpen(nextOpen)}>\n <Popover.Trigger asChild>\n <Button variant='ghost' classNames='p-0'>\n <CaretDown className={getSize(4)} />\n </Button>\n </Popover.Trigger>\n <Popover.Portal>\n <Popover.Content>\n <Popover.Viewport classNames='w-60'>\n <DensityProvider density='fine'>\n <div className='flex flex-col gap-1'>\n <Section>\n <Input.Root>\n <Input.Label classNames='mbe-1'>Label</Input.Label>\n <Input.TextInput\n placeholder='Column label'\n value={label ?? ''}\n onChange={(event) => setLabel(event.target.value)}\n autoFocus\n />\n </Input.Root>\n <Input.Root>\n <Input.Label classNames='mbe-1 mbs-3'>Property</Input.Label>\n <Input.TextInput\n ref={propRef}\n placeholder='Property key'\n // TODO(burdon): Provide hooks for value normalization, ENTER, ESC, etc.\n value={prop ?? ''}\n onChange={(event) => setProp(event.target.value.replace(/[^\\w_]/g, ''))}\n />\n </Input.Root>\n <Input.Root>\n <Input.Label classNames='mbe-1 mbs-3'>Type</Input.Label>\n <Select.Root value={type} onValueChange={setType}>\n <Select.TriggerButton placeholder='Type' classNames='is-full' />\n <Select.Portal>\n <Select.Content>\n <Select.Viewport>\n {Array.from(columnTypes.entries()).map(([type, label]) => (\n <Select.Option key={type} value={type}>\n {label}\n </Select.Option>\n ))}\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n </Input.Root>\n </Section>\n\n {type === 'number' && (\n <>\n <Section>\n <Input.Root>\n <Input.Label classNames='mbe-1 mbs-3'>Decimal places</Input.Label>\n {/* TODO(burdon): Constrain input to numbers. */}\n <Input.TextInput value={digits ?? ''} onChange={(event) => setDigits(event.target.value)} />\n </Input.Root>\n </Section>\n </>\n )}\n\n {/* TODO(burdon): Selectors on same line. */}\n {type === 'ref' && (\n <>\n <Section>\n <Input.Root>\n <Input.Label classNames='mbe-1 mbs-3'>Table</Input.Label>\n <Select.Root value={refTable} onValueChange={setRefTable}>\n <Select.TriggerButton placeholder='Table' classNames='is-full' />\n <Select.Portal>\n <Select.Content>\n <Select.Viewport>\n {tableDefs\n .filter((t) => t.id !== tableDef.id)\n .map(({ id, name }) => (\n <Select.Option key={id} value={id}>\n {name ?? id}\n </Select.Option>\n ))}\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n </Input.Root>\n\n {refTable && (\n <Input.Root>\n <Input.Label classNames='mbe-1 mbs-3'>Table property</Input.Label>\n <Select.Root value={refProp} onValueChange={setRefProp}>\n <Select.TriggerButton placeholder='Property' classNames='is-full' />\n <Select.Portal>\n <Select.Content>\n <Select.Viewport>\n {tableDefs\n .find((tableDef) => tableDef.id === refTable)\n ?.columns.map(({ id, label }) => (\n <Select.Option key={id} value={id}>\n {label ?? id}\n </Select.Option>\n ))}\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n </Input.Root>\n )}\n </Section>\n </>\n )}\n\n <Separator classNames='mli-2' />\n\n <Section className='space-b-1.5'>\n {/* TODO(burdon): Style as DropdownMenuItem. */}\n <Button variant='primary' classNames='is-full flex gap-2' onClick={handleSave}>\n <span>Save</span>\n <div className='grow' />\n <Check className={getSize(5)} />\n </Button>\n <Button classNames='is-full flex gap-2' onClick={handleCancel}>\n <span>Cancel</span>\n <div className='grow' />\n <X className={getSize(5)} />\n </Button>\n <Button classNames='is-full flex gap-2' onClick={() => onDelete?.(column.id)}>\n <span>Delete</span>\n <div className='grow' />\n <Trash className={getSize(5)} />\n </Button>\n </Section>\n </div>\n </DensityProvider>\n </Popover.Viewport>\n <Popover.Arrow />\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n );\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nexport type TableDef = {\n id: string;\n name?: string; // TODO(burdon): Required?\n columns: ColumnProps[];\n};\n\nexport type ColumnType = 'number' | 'boolean' | 'date' | 'string' | 'ref';\n\nexport const columnTypes = new Map<ColumnType, string>([\n ['string', 'Text'],\n ['boolean', 'Checkbox'],\n ['number', 'Number'],\n ['date', 'Date'],\n ['ref', 'Reference'],\n]);\n\nexport type ColumnProps = {\n id: string;\n prop: string;\n type: ColumnType;\n size?: number;\n label?: string;\n\n // type = number\n digits?: number;\n\n // type = ref\n refTable?: string;\n refProp?: string;\n\n // TODO(burdon): Move to meta.\n fixed?: boolean;\n editable?: boolean;\n resizable?: boolean;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport {\n flexRender,\n getCoreRowModel,\n getGroupedRowModel,\n useReactTable,\n type ColumnSizingInfoState,\n type ColumnSizingState,\n type GroupingState,\n type HeaderGroup,\n type Row,\n type RowData,\n type RowSelectionState,\n type TableState,\n type VisibilityState,\n} from '@tanstack/react-table';\nimport React, { Fragment, useEffect, useRef, useState } from 'react';\n\nimport { debounce } from '@dxos/async';\nimport { groupBorder, inputSurface, mx } from '@dxos/react-ui-theme';\n\nimport { defaultTableSlots, type TableSlots } from '../theme';\nimport { type TableColumnDef, type KeyValue } from '../types';\n\n// TODO(burdon): Sort/filter.\n// TODO(burdon): Drag-and-drop.\n// TODO(burdon): Virtual (e.g., log panel).\n\nexport type TableSelection<TData extends RowData> = {\n // Controlled if undefined (by default).\n select?: 'single' | 'single-toggle' | 'multiple' | 'multiple-toggle' | undefined;\n selected?: TData[];\n onSelectedChange?: (selected: TData[] | undefined) => void;\n};\n\n/**\n * Util to update the selection based on the mode.\n */\nexport const updateSelection = (\n selectionState: RowSelectionState,\n id: string,\n selection: TableSelection<any>['select'],\n): RowSelectionState => {\n switch (selection) {\n case 'single': {\n return {\n [id]: true,\n };\n }\n case 'single-toggle': {\n return selectionState[id]\n ? {}\n : {\n [id]: true,\n };\n }\n case 'multiple': {\n return {\n [id]: true,\n ...selectionState,\n };\n }\n case 'multiple-toggle': {\n if (selectionState[id]) {\n const newSelectionState = { ...selectionState };\n delete newSelectionState[id];\n return newSelectionState;\n } else {\n return {\n [id]: true,\n ...selectionState,\n };\n }\n }\n }\n\n return selectionState;\n};\n\nexport type TableProps<TData extends RowData> = {\n keyAccessor?: KeyValue<TData>;\n data?: TData[];\n columns?: TableColumnDef<TData>[];\n columnVisibility?: VisibilityState;\n onColumnResize?: (state: Record<string, number>) => void;\n grouping?: string[];\n header?: boolean;\n footer?: boolean;\n border?: boolean;\n fullWidth?: boolean;\n pinToBottom?: boolean;\n slots?: TableSlots;\n debug?: boolean;\n} & TableSelection<TData>;\n\nexport const Table = <TData extends RowData>({ slots = defaultTableSlots, ...props }: TableProps<TData>) => {\n const {\n data = [],\n columns = [],\n onColumnResize,\n columnVisibility,\n header = true,\n footer,\n select,\n selected,\n onSelectedChange,\n fullWidth,\n pinToBottom,\n debug,\n } = props;\n\n // Update controlled selection.\n // https://tanstack.com/table/v8/docs/api/features/row-selection\n const [focus, setFocus] = useState<string>();\n const [rowSelection, setRowSelection] = useState<RowSelectionState>({});\n useEffect(() => {\n setRowSelection(\n selected?.reduce((selectionState: RowSelectionState, selected) => {\n const row = table.getRowModel().rows.find((row) => row.original === selected);\n if (row) {\n selectionState[row.id] = true;\n }\n\n return selectionState;\n }, {}) ?? {},\n );\n }, [select, selected]);\n\n // Resizing.\n const [columnSizingInfo, setColumnSizingInfo] = useState<ColumnSizingInfoState>({} as ColumnSizingInfoState);\n const onColumnResizeDebounced = debounce<ColumnSizingState>((info) => onColumnResize?.(info), 500);\n useEffect(() => {\n if (columnSizingInfo.columnSizingStart?.length === 0) {\n onColumnResizeDebounced(table.getState().columnSizing);\n }\n }, [columnSizingInfo]);\n\n const [grouping, setGrouping] = useState<GroupingState>(props.grouping ?? []);\n useEffect(() => setGrouping(props.grouping ?? []), [props.grouping]);\n\n //\n // Update table state.\n // https://tanstack.com/table/v8/docs/api/core/table\n //\n const table = useReactTable({\n data,\n columns,\n defaultColumn: {\n size: 400, // Required in order remove default width.\n maxSize: 800,\n },\n getCoreRowModel: getCoreRowModel(),\n meta: {},\n\n // TODO(burdon): Pagination.\n // TODO(burdon): Sorting.\n // TODO(burdon): Filtering.\n state: {\n columnVisibility,\n columnSizingInfo,\n rowSelection,\n grouping,\n },\n\n // Grouping.\n getGroupedRowModel: getGroupedRowModel(),\n onGroupingChange: setGrouping,\n\n // Selection.\n enableRowSelection: select === 'single' || select === 'single-toggle',\n enableMultiRowSelection: select === 'multiple' || select === 'multiple-toggle',\n onRowSelectionChange: (rows) => {\n setRowSelection(rows);\n },\n\n // Resize columns.\n // TODO(burdon): Drag to re-order columns.\n columnResizeMode: 'onChange',\n enableColumnResizing: true,\n onColumnSizingInfoChange: setColumnSizingInfo,\n\n debugTable: debug,\n });\n\n // TODO(burdon): Add flex if not resizable.\n // Create additional expansion column if all columns have fixed width.\n const expand = false; // columns.map((column) => column.size).filter(Boolean).length === columns?.length;\n\n // Pin scrollbar to bottom.\n const containerRef = usePinToBottom(data, pinToBottom);\n\n const handleSelect = (row: Row<TData>) => {\n if (select) {\n // Uncontrolled.\n setRowSelection((selectionState: RowSelectionState) => {\n const newSelectionState = updateSelection(selectionState, row.id, select);\n if (onSelectedChange) {\n const rows: TData[] = Object.keys(newSelectionState).map((id) => table.getRowModel().rowsById[id].original);\n onSelectedChange(rows);\n }\n\n return newSelectionState;\n });\n } else {\n // Controlled.\n onSelectedChange?.([row.original]);\n }\n };\n\n // TODO(burdon): Use radix ScrollArea.\n // https://www.radix-ui.com/primitives/docs/components/scroll-area\n return (\n <div ref={containerRef} className={mx('grow overflow-auto', slots?.root?.className)}>\n <table\n // Styles:\n // table-fixed: Prevents fixed sized columns from shrinking.\n className={mx(!fullWidth && 'table-fixed', inputSurface, slots?.table?.className)}\n style={{\n width: fullWidth ? '100%' : table.getTotalSize(),\n }}\n >\n {/* Head */}\n <TableHead\n {...props}\n slots={slots}\n header={header}\n state={table.getState()}\n headers={table.getHeaderGroups()}\n />\n\n {/* Rows */}\n {grouping.length === 0 && (\n <TableBody\n {...props}\n slots={slots}\n rowSelection={rowSelection}\n expand={expand}\n focus={focus}\n onFocus={setFocus}\n onSelect={handleSelect}\n rows={table.getRowModel().rows}\n />\n )}\n\n {/* Groups */}\n {grouping.length !== 0 &&\n table.getGroupedRowModel().rows.map((row, i) => {\n return (\n <Fragment key={i}>\n {/* TODO(burdon): Customize group header renderer. */}\n <thead>\n <tr>\n {slots?.margin && <th className={mx(slots?.margin?.className)} />}\n {debug && <th />}\n <th\n // TODO(burdon): Calculate row span.\n colSpan={table.getHeaderGroups()[0].headers.length}\n className={mx('text-left', slots?.group?.className)}\n >\n {table.getState().grouping[0]}[{String(row.getGroupingValue(table.getState().grouping[0]))}]\n </th>\n </tr>\n </thead>\n\n <TableBody\n {...props}\n slots={slots}\n rowSelection={rowSelection}\n expand={expand}\n focus={focus}\n onFocus={setFocus}\n onSelect={handleSelect}\n rows={row.subRows}\n />\n </Fragment>\n );\n })}\n\n {/* Foot */}\n {footer && <TableFoot {...props} slots={slots} footers={table.getFooterGroups()} />}\n </table>\n\n {debug && (\n <pre className='font-mono text-xs text-neutral-500 my-4 p-2 ring'>\n <code>{JSON.stringify(table.getState(), undefined, 2)}</code>\n </pre>\n )}\n </div>\n );\n};\n\n/**\n * Glue to bottom as rows are added.\n */\n// TODO(burdon): Causes scrollbar to be constantly visible.\n// https://css-tricks.com/books/greatest-css-tricks/pin-scrolling-to-bottom\nconst usePinToBottom = <TData extends RowData>(data: TData[], pinToBottom?: boolean) => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [stickyScrolling, setStickyScrolling] = useState(true);\n useEffect(() => {\n const container = containerRef.current;\n if (!pinToBottom || !container) {\n return;\n }\n\n // TODO(burdon): Set when scrolled to bottom and unset when manually scrolled away.\n const handler = () => {\n const bottom = container.scrollHeight - container.scrollTop - container.clientHeight === 0;\n setStickyScrolling(bottom);\n };\n\n container.addEventListener('scroll', handler);\n return () => container.removeEventListener('scroll', handler);\n }, []);\n\n useEffect(() => {\n if (!pinToBottom || !containerRef.current || !stickyScrolling) {\n return;\n }\n\n containerRef.current?.scroll({ top: containerRef.current.scrollHeight });\n }, [data]);\n\n return containerRef;\n};\n\n//\n// Head.\n//\n\ntype TableHeadProps<TData extends RowData> = Partial<TableProps<TData>> & {\n state: TableState;\n headers: HeaderGroup<TData>[];\n expand?: boolean;\n};\n\nconst TableHead = <TData extends RowData>({\n state,\n headers,\n expand,\n header,\n debug,\n fullWidth,\n border,\n slots,\n}: TableHeadProps<TData>) => {\n return (\n <thead className={mx(header ? ['sticky top-0 z-10'] : 'collapse')}>\n {headers.map((headerGroup) => {\n return (\n // Group element to hover resize handles.\n <tr key={headerGroup.id} className='font-light group'>\n {slots?.margin && <th className={mx(slots?.margin?.className)} />}\n\n {/* TODO(burdon): Calc. width. */}\n {debug && (\n <th className='text-left' style={{ width: 32 }}>\n #\n </th>\n )}\n\n {headerGroup.headers.map((header) => {\n return (\n <th\n key={header.id}\n style={{\n // Don't set width if fullWidth and no explicit size.\n width: fullWidth && header.column.columnDef.meta?.expand ? undefined : header.getSize(),\n }}\n // Relative for resize handle.\n // TODO(burdon): Border scrolls with main content.\n // https://stackoverflow.com/questions/50361698/border-style-do-not-work-with-sticky-position-element\n className={mx(\n 'relative text-left',\n border && groupBorder,\n slots?.header?.className,\n header.column.columnDef.meta?.slots?.header?.className,\n )}\n >\n {!header || header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n\n {/*\n * Resize handle.\n * https://codesandbox.io/p/sandbox/github/tanstack/table/tree/main/examples/react/column-sizing\n */}\n {header.column.columnDef.meta?.resizable && (\n <div\n className={mx(\n 'absolute top-0 pl-1 h-full z-[10] w-[7px] -right-[5px]',\n 'cursor-col-resize select-none touch-none opacity-20 hover:opacity-100',\n header.column.getIsResizing() && 'hidden',\n )}\n style={{\n transform: header.column.getIsResizing()\n ? `translateX(${state.columnSizingInfo.deltaOffset}px)`\n : undefined,\n }}\n onMouseDown={header.getResizeHandler()}\n onTouchStart={header.getResizeHandler()}\n >\n <div className='flex group-hover:bg-neutral-700 -ml-[2px] w-[1px] h-full' />\n </div>\n )}\n </th>\n );\n })}\n {expand && <th />}\n {slots?.margin && <th className={mx(slots?.margin?.className)} />}\n </tr>\n );\n })}\n </thead>\n );\n};\n\n//\n// Body.\n//\n\ntype TableBodyProps<TData extends RowData> = Partial<TableProps<TData>> & {\n rows: Row<TData>[];\n rowSelection: RowSelectionState;\n expand?: boolean;\n focus?: string;\n onFocus?: (id?: string) => void;\n onSelect?: (row: Row<TData>) => void;\n};\n\nconst TableBody = <TData extends RowData>({\n keyAccessor,\n rows,\n rowSelection,\n focus,\n onFocus,\n onSelect,\n debug,\n border,\n expand,\n slots,\n}: TableBodyProps<TData>) => {\n return (\n <tbody>\n {rows.map((row) => {\n return (\n <tr\n key={keyAccessor ? keyAccessor(row.original) : row.id}\n onClick={() => onSelect?.(row)}\n role='button' // TODO(burdon): ???\n className={mx(\n 'group',\n rowSelection[row.id] && slots?.selected?.className,\n focus === row.id && slots?.focus?.className,\n slots?.row?.className,\n )}\n >\n {/* TODO(burdon): Dummy button for focus (don't alter geometry). */}\n {slots?.margin && (\n <td className={mx(slots?.margin?.className)}>\n <button\n role='button'\n style={{ width: 1, height: 1 }}\n className='focus:outline-none'\n onFocus={() => onFocus?.(keyAccessor ? keyAccessor(row.original) : row.id)}\n onBlur={() => onFocus?.(undefined)}\n onKeyDown={(event) => {\n // TODO(burdon): Move focus.\n switch (event.key) {\n case 'ArrowUp': {\n break;\n }\n case 'ArrowDown': {\n break;\n }\n }\n }}\n />\n </td>\n )}\n\n {debug && <td>{row.id}</td>}\n\n {row.getVisibleCells().map((cell) => {\n // TODO(burdon): Allow class override from column.\n return (\n <td\n key={cell.id}\n className={mx(\n border && groupBorder,\n slots?.cell?.className,\n cell.column.columnDef.meta?.slots?.cell?.className,\n )}\n >\n {flexRender(cell.column.columnDef.cell, { className: 'px-2', ...cell.getContext() })}\n </td>\n );\n })}\n\n {expand && <td />}\n {slots?.margin && <td className={mx(slots?.margin?.className)} />}\n </tr>\n );\n })}\n </tbody>\n );\n};\n\n//\n// Footer\n//\n\ntype TableFootProps<TData extends RowData> = Partial<TableProps<TData>> & {\n footers: HeaderGroup<TData>[];\n expand?: boolean;\n};\n\nconst TableFoot = <TData extends RowData>({ footers, expand, slots, debug, border }: TableFootProps<TData>) => {\n return (\n <tfoot className={mx('sticky bottom-0 z-[10]', slots?.footer?.className)}>\n {footers.map((footerGroup) => (\n <tr key={footerGroup.id} className='font-thin'>\n {slots?.margin && <th className={mx(slots?.margin?.className)} />}\n {debug && <th />}\n\n {footerGroup.headers.map((footer) => {\n return (\n <th\n key={footer.id}\n className={mx(\n border && groupBorder,\n 'text-left',\n slots?.footer?.className,\n footer.column.columnDef.meta?.slots?.footer?.className,\n )}\n >\n {footer.isPlaceholder ? null : flexRender(footer.column.columnDef.footer, footer.getContext())}\n </th>\n );\n })}\n\n {expand && <th />}\n {slots?.margin && <th className={mx(slots?.margin?.className)} />}\n </tr>\n ))}\n </tfoot>\n );\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { chromeSurface } from '@dxos/react-ui-theme';\n\n// TODO(burdon): Remove nested classNames? Add to theme?\nexport type TableSlots = {\n root?: {\n className?: string | string[];\n };\n table?: {\n className?: string | string[];\n };\n header?: {\n className?: string | string[];\n };\n footer?: {\n className?: string | string[];\n };\n group?: {\n className?: string | string[];\n };\n row?: {\n className?: string | string[];\n };\n cell?: {\n className?: string | string[];\n };\n focus?: {\n className?: string | string[];\n };\n selected?: {\n className?: string | string[];\n };\n margin?: {\n className?: string | string[];\n };\n};\n\n// TODO(burdon): Change to groups.\n/*\nhead: {\n default:\n cell:\n}\nrow: {\n default: '',\n selected: ''\n}\n*/\n\n// TODO(burdon): Scrollbar area.\n// TODO(burdon): Overscroll horizontal (full width).\n\n// TODO(burdon): Integrate with DXOS UI theme (direct dependency -- see react-ui-editor, tailwind.ts).\n// See Link.tsx const { tx } = useThemeContext();\n// Reuse button fragments for hoverColors, selected, primary, etc.\nexport const defaultTableSlots: TableSlots = {\n // TODO(burdon): head/body/table rows.\n header: { className: [chromeSurface, 'px-2 font-light select-none'] },\n footer: { className: [chromeSurface, 'px-2 font-light'] },\n cell: { className: 'px-2' },\n group: { className: 'px-2 font-light text-xs text-left' },\n focus: { className: 'ring ring-primary-600 ring-inset' },\n selected: { className: '!bg-teal-100 dark:!bg-teal-700' },\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { CaretDown } from '@phosphor-icons/react';\nimport { type RowData } from '@tanstack/react-table';\nimport React, { useCallback, useState } from 'react';\n\nimport { Popover, useTranslation } from '@dxos/react-ui';\nimport { PopoverCombobox } from '@dxos/react-ui-searchlist';\nimport { descriptionText, getSize, mx, staticPlaceholderText } from '@dxos/react-ui-theme';\n\nimport { type SelectQueryModel } from '../helpers';\nimport { translationKey } from '../translations';\n\nexport type ComboboxCellItems<TData extends RowData> = Record<string, { label: string; data: TData }>;\n\nconst initialItems = <TData extends RowData>(model: SelectQueryModel<TData>, value?: TData) =>\n value\n ? {\n [model.getId(value)]: { label: model.getText(value), data: value },\n }\n : {};\n\nexport const ComboboxCell = <TData extends RowData>({\n model,\n value,\n onValueChange,\n}: {\n model: SelectQueryModel<TData>;\n value: TData;\n onValueChange: (value: TData) => void;\n}) => {\n const { t } = useTranslation(translationKey);\n const [items, setItems] = useState<ComboboxCellItems<TData>>(initialItems(model, value));\n const [loading, setLoading] = useState(false);\n const [searchInputValue, setSearchInputValue] = useState('');\n const handleSearchInputValueChange = async (text?: string) => {\n setSearchInputValue(text ?? '');\n setLoading(true);\n const items = await model.query(text);\n setItems(\n items.reduce((acc: ComboboxCellItems<TData>, item) => {\n acc[model.getId(item)] = {\n label: model.getText(item),\n data: item,\n };\n return acc;\n }, initialItems(model, value)),\n );\n setLoading(false);\n };\n\n const handleValueChange = useCallback(\n (id: string) => {\n onValueChange(items[id]?.data);\n },\n [items, onValueChange],\n );\n\n return (\n <PopoverCombobox.Root placeholder={t('no selection label')}>\n <PopoverCombobox.Trigger variant='ghost' classNames='is-full'>\n {value ? (\n <>\n <span\n className={mx('font-normal text-start flex-1 min-is-0 truncate mie-2', !value && staticPlaceholderText)}\n >\n {model.getText(value)}\n </span>\n <CaretDown weight='bold' className={getSize(3)} />\n </>\n ) : null}\n </PopoverCombobox.Trigger>\n <PopoverCombobox.Content shouldFilter={false} classNames='is-[--radix-popover-trigger-width]'>\n <PopoverCombobox.Input value={searchInputValue} onValueChange={handleSearchInputValueChange} />\n <PopoverCombobox.List>\n {searchInputValue.length < 1 ? (\n <p className={mx('text-center', descriptionText)}>Start typing to search</p>\n ) : loading ? (\n <p className={mx('text-center', descriptionText)}>Searching…</p>\n ) : (\n <>\n <PopoverCombobox.Empty classNames={['text-center', descriptionText]}>No results</PopoverCombobox.Empty>\n {Object.entries(items).map(([id, { label }]) => (\n <PopoverCombobox.Item key={id} value={id} onSelect={handleValueChange} classNames='truncate'>\n {label}\n </PopoverCombobox.Item>\n ))}\n </>\n )}\n </PopoverCombobox.List>\n <Popover.Arrow />\n </PopoverCombobox.Content>\n </PopoverCombobox.Root>\n );\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nexport const translationKey = 'table';\n\nexport default [\n {\n 'en-US': {\n [translationKey]: {\n 'no selection label': ' ',\n },\n },\n },\n];\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { useFocusFinders } from '@fluentui/react-tabster';\nimport { Check, ClipboardText, type Icon, X } from '@phosphor-icons/react';\nimport { createColumnHelper, type ColumnDef, type ColumnMeta, type RowData } from '@tanstack/react-table';\nimport format from 'date-fns/format';\nimport formatDistanceToNow from 'date-fns/formatDistanceToNow';\nimport defaultsDeep from 'lodash.defaultsdeep';\nimport React, { useRef, useState } from 'react';\n\nimport { type PublicKey } from '@dxos/keys';\nimport { Input, Tooltip } from '@dxos/react-ui';\nimport { getSize, mx } from '@dxos/react-ui-theme';\nimport { stripUndefinedValues } from '@dxos/util';\n\nimport { ComboboxCell } from './components';\n\n// TODO(burdon): Factor out hack to find next focusable element (extend useFocusFinders)?\nconst findNextFocusable = (\n findFirstFocusable: (container: HTMLElement) => HTMLElement | null | undefined,\n container: HTMLElement,\n): HTMLElement | undefined => {\n const next = findFirstFocusable(container as any);\n if (next) {\n if (next?.tagName === 'INPUT') {\n return next;\n }\n if (container.nextElementSibling) {\n return findNextFocusable(findFirstFocusable, container.nextSibling as any);\n }\n }\n};\n\nexport type ValueUpdater<TData extends RowData, TValue> = (row: TData, id: string, value: TValue) => void;\n\nexport const createColumnBuilder = <TData extends RowData>() => ({\n helper: createColumnHelper<TData>(),\n builder: new ColumnBuilder<TData>(),\n});\n\n/**\n * NOTE: Can use `meta` for custom properties.\n */\nexport type BaseColumnOptions<TData, TValue> = Partial<ColumnDef<TData, TValue>> & {\n meta?: ColumnMeta<TData, TValue>;\n label?: string;\n className?: string;\n onUpdate?: ValueUpdater<TData, TValue | undefined>;\n};\n\n// TODO(burdon): Better abstraction?\nexport type SelectQueryModel<TData extends RowData> = {\n getId(object: TData): string;\n getText(object: TData): string;\n query(text?: string): Promise<TData[]>;\n};\n\nexport type SelectColumnOptions<TData extends RowData> = BaseColumnOptions<TData, any> & {\n model: SelectQueryModel<TData>;\n};\n\nexport type StringColumnOptions<TData extends RowData> = BaseColumnOptions<TData, string> & {};\n\nexport type NumberColumnOptions<TData extends RowData> = BaseColumnOptions<TData, number> & {\n digits?: number;\n};\n\nexport type KeyColumnOptions<TData extends RowData> = BaseColumnOptions<TData, PublicKey> & {\n tooltip?: boolean;\n};\n\nexport type DateColumnOptions<TData extends RowData> = BaseColumnOptions<TData, Date> & {\n format?: string;\n relative?: boolean;\n};\n\nexport type BooleanColumnOptions<TData extends RowData> = BaseColumnOptions<TData, boolean> & {};\n\nexport type IconColumnOptions<TData extends RowData> = BaseColumnOptions<TData, boolean> & {\n on?: {\n Icon?: Icon;\n className?: string;\n };\n off?: {\n Icon?: Icon;\n className?: string;\n };\n};\n\nconst defaults = <TData extends RowData, TValue>(\n options: Partial<ColumnDef<TData, TValue>>,\n ...sources: Partial<ColumnDef<TData, TValue>>[]\n): Partial<ColumnDef<TData, TValue>> => {\n return stripUndefinedValues(defaultsDeep({}, options, ...sources));\n};\n\n/**\n * Util to create column definitions.\n */\nexport class ColumnBuilder<TData extends RowData> {\n /**\n * Select value\n */\n select({ label, className, model, onUpdate, ...props }: SelectColumnOptions<TData>): Partial<ColumnDef<TData, any>> {\n return defaults(props, {\n minSize: 100,\n header: (column) => {\n return <div className={'truncate'}>{label ?? column.header.id}</div>;\n },\n cell:\n model && onUpdate\n ? (cell) => (\n <ComboboxCell<any>\n model={model}\n value={cell.getValue()}\n onValueChange={(value) => onUpdate?.(cell.row.original, cell.column.id, value)}\n />\n )\n : (cell) => {\n const value = cell.getValue();\n return <div className={mx('truncate', className)}>{value ? model.getText(value) : ''}</div>;\n },\n });\n }\n\n /**\n * String formats.\n */\n string({ label, className, onUpdate, ...props }: StringColumnOptions<TData> = {}): Partial<ColumnDef<TData, string>> {\n return defaults(props, {\n minSize: 100,\n // TODO(burdon): Default.\n header: (column) => {\n return <div className={'truncate'}>{label ?? column.header.id}</div>;\n },\n cell: onUpdate\n ? (cell) => {\n // https://tanstack.com/table/v8/docs/examples/react/editable-data\n const initialValue = cell.getValue();\n const [value, setValue] = useState(initialValue);\n const inputRef = useRef<HTMLInputElement>(null);\n const { findFirstFocusable } = useFocusFinders();\n\n const handleSave = (focusNext = false) => {\n if (value === initialValue) {\n return;\n }\n\n onUpdate?.(cell.row.original, cell.column.id, value);\n\n // TODO(burdon): More generally support keyboard navigation.\n if (focusNext) {\n const rowElement = inputRef.current?.parentElement?.parentElement;\n // TODO(burdon): Hack to wait for next row to render.\n setTimeout(() => {\n const next = findNextFocusable(findFirstFocusable, rowElement as HTMLElement);\n next?.focus();\n });\n }\n };\n\n const handleCancel = () => {\n setValue(initialValue);\n };\n\n // Check if first input column of last row.\n const rows = cell.table.getRowModel().flatRows;\n const columns = cell.table.getVisibleFlatColumns();\n const placeholder = cell.row.index === rows.length - 1 && columns[0].id === cell.column.id;\n\n // TODO(burdon): Don't render inputs unless mouse over (Show ellipsis when div)?\n return (\n <Input.Root>\n <Input.TextInput\n ref={inputRef}\n variant='subdued'\n placeholder={placeholder ? 'Add row...' : undefined}\n classNames={'px-2'}\n value={(value as string) ?? ''}\n onBlur={() => handleSave(false)}\n onChange={(event) => setValue(event.target.value)}\n onKeyDown={(event) =>\n (event.key === 'Enter' && handleSave(true)) || (event.key === 'Escape' && handleCancel())\n }\n />\n </Input.Root>\n );\n }\n : (cell) => {\n const value = cell.getValue();\n return <div className={mx('truncate', className)}>{value}</div>;\n },\n });\n }\n\n /**\n * Number formats.\n */\n number({ label, minSize, className, digits, onUpdate, ...props }: NumberColumnOptions<TData> = {}): Partial<\n ColumnDef<TData, number>\n > {\n return defaults(props, {\n size: 100,\n minSize: 100,\n header: (cell) => <div className='w-full truncate text-right'>{label ?? cell.header.id}</div>,\n cell: (cell) => {\n const value = cell.getValue();\n const [text, setText] = useState<string>();\n\n const handleEdit = () => {\n if (onUpdate) {\n setText(value !== undefined ? String(value) : '');\n }\n };\n\n // TODO(burdon): Property is encoded as float (e.g., 6.1 => 6.099)\n const handleSave = () => {\n const value = text?.trim().length ? Number(text) : NaN;\n onUpdate?.(cell.row.original, cell.column.id, isNaN(value) ? undefined : value);\n setText(undefined);\n };\n\n const handleCancel = () => {\n setText(undefined);\n };\n\n if (text !== undefined) {\n return (\n <div className={mx('grow text-right font-mono', className)}>\n <Input.Root>\n <Input.TextInput\n autoFocus\n value={text}\n classNames={'px-2'}\n onBlur={handleSave}\n onChange={(event) => setText(event.target.value)}\n onKeyDown={(event) =>\n (event.key === 'Escape' && handleCancel()) || (event.key === 'Enter' && handleSave())\n }\n />\n </Input.Root>\n </div>\n );\n }\n\n return (\n <div\n className={mx('grow w-full text-right font-mono empty:after:content-[\" \"]', className)}\n onClick={handleEdit}\n >\n {value?.toLocaleString(undefined, {\n minimumFractionDigits: digits ?? 0,\n maximumFractionDigits: digits ?? 2,\n })}\n </div>\n );\n },\n });\n }\n\n /**\n * Date formats.\n */\n // TODO(burdon): Date picker (pluggable renderers?)\n date({ label, format: formatSpec, relative, className, ...props }: DateColumnOptions<TData> = {}): Partial<\n ColumnDef<TData, Date>\n > {\n return defaults(props, {\n size: 220, // TODO(burdon): Depends on format.\n minSize: 100,\n header: (cell) => <div>{label ?? cell.header.id}</div>,\n cell: (cell) => {\n const value = cell.getValue();\n\n try {\n const str = value\n ? formatSpec\n ? format(value, formatSpec)\n : relative\n ? formatDistanceToNow(value, { addSuffix: true })\n : value.toISOString()\n : undefined;\n\n return <div className={mx('font-mono', className)}>{str}</div>;\n } catch (err) {\n console.log(value);\n return null;\n }\n },\n });\n }\n\n /**\n * PublicKey with tooltip.\n */\n key({ label, tooltip, ...props }: KeyColumnOptions<TData> = {}): Partial<ColumnDef<TData, PublicKey>> {\n return defaults(props, {\n size: 86,\n minSize: 86,\n header: (cell) => <div>{label ?? cell.header.id}</div>,\n cell: (cell) => {\n const value = cell.getValue();\n if (!value) {\n return;\n }\n\n // TODO(burdon): Factor out styles.\n const element = (\n <div className='font-mono font-thin text-green-500 dark:text-green-300'>{value.truncate()}</div>\n );\n if (!tooltip) {\n return element;\n }\n\n return (\n <div className='group inline-flex gap-2 items-center'>\n <Tooltip.Provider>\n <Tooltip.Root>\n <Tooltip.Trigger asChild>{element}</Tooltip.Trigger>\n <Tooltip.Content side='right'>\n <Tooltip.Arrow />\n <ClipboardText\n onClick={(ev) => {\n ev.stopPropagation(); // Prevent select row.\n void navigator.clipboard.writeText(value.toHex());\n }}\n />\n </Tooltip.Content>\n </Tooltip.Root>\n </Tooltip.Provider>\n </div>\n );\n },\n });\n }\n\n /**\n * Checkbox.\n */\n checkbox({ label, className, onUpdate, ...props }: BooleanColumnOptions<TData> = {}): Partial<\n ColumnDef<TData, boolean>\n > {\n return defaults(props, {\n size: 40,\n minSize: 40,\n header: (column) => <div className={'flex grow justify-center'}>{label ?? column.header.id}</div>,\n cell: (cell) => {\n const value = cell.getValue();\n // TODO(burdon): Center.\n return (\n <div className='flex grow justify-center'>\n <Input.Root>\n <Input.Checkbox\n onClick={(event) => event.stopPropagation()}\n classNames={className}\n disabled={!onUpdate}\n checked={!!value}\n onCheckedChange={(value) => {\n onUpdate?.(cell.row.original, cell.column.id, !!value);\n }}\n />\n </Input.Root>\n </div>\n );\n },\n });\n }\n\n /**\n * Icon based on boolean value.\n */\n icon({ label, size, on, off, ...props }: IconColumnOptions<TData> = {}): Partial<ColumnDef<TData, boolean>> {\n const IconOn = on?.Icon ?? Check;\n const IconOff = off?.Icon ?? X;\n return defaults(props, {\n size: size ?? 32,\n header: (column) => <div className={'justify-center'}>{label ?? column.header.id}</div>,\n cell: (cell) => {\n const value = cell.getValue();\n if (value) {\n return (\n <div className='flex grow justify-center'>\n <IconOn className={mx(getSize(6), on?.className ?? 'text-green-700')} />\n </div>\n );\n } else if (value === false) {\n return (\n <div className='flex grow justify-center'>\n <IconOff className={mx(getSize(6), off?.className ?? 'text-red-700')} />\n </div>\n );\n } else {\n return null;\n }\n },\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Check", "CaretDown", "Trash", "X", "React", "useRef", "useState", "Button", "DensityProvider", "Input", "Popover", "Select", "Separator", "getSize", "mx", "safeParseInt", "columnTypes", "Map", "ColumnMenu", "column", "props", "title", "label", "length", "id", "div", "className", "ColumnPanel", "Section", "children", "role", "mx", "context", "tableDefs", "tableDef", "onUpdate", "onDelete", "open", "setOpen", "useState", "prop", "setProp", "refTable", "setRefTable", "refProp", "setRefProp", "type", "setType", "String", "setLabel", "digits", "setDigits", "propRef", "useRef", "handleCancel", "handleSave", "match", "current", "focus", "columns", "find", "c", "safeParseInt", "Popover", "Root", "onOpenChange", "nextOpen", "Trigger", "asChild", "Button", "variant", "classNames", "CaretDown", "getSize", "Portal", "Content", "Viewport", "DensityProvider", "density", "Input", "Label", "TextInput", "placeholder", "value", "onChange", "event", "target", "autoFocus", "ref", "replace", "Select", "onValueChange", "TriggerButton", "Array", "from", "columnTypes", "entries", "map", "Option", "key", "filter", "t", "name", "Separator", "onClick", "span", "Check", "X", "Trash", "Arrow", "flexRender", "getCoreRowModel", "getGroupedRowModel", "useReactTable", "React", "Fragment", "useEffect", "useRef", "useState", "debounce", "groupBorder", "inputSurface", "mx", "chromeSurface", "defaultTableSlots", "header", "className", "chromeSurface", "footer", "cell", "group", "focus", "selected", "updateSelection", "selectionState", "id", "selection", "newSelectionState", "Table", "slots", "defaultTableSlots", "props", "data", "columns", "onColumnResize", "columnVisibility", "header", "footer", "select", "selected", "onSelectedChange", "fullWidth", "pinToBottom", "debug", "focus", "setFocus", "useState", "rowSelection", "setRowSelection", "useEffect", "reduce", "row", "table", "getRowModel", "rows", "find", "original", "columnSizingInfo", "setColumnSizingInfo", "onColumnResizeDebounced", "debounce", "info", "columnSizingStart", "length", "getState", "columnSizing", "grouping", "setGrouping", "useReactTable", "defaultColumn", "size", "maxSize", "getCoreRowModel", "meta", "state", "getGroupedRowModel", "onGroupingChange", "enableRowSelection", "enableMultiRowSelection", "onRowSelectionChange", "columnResizeMode", "enableColumnResizing", "onColumnSizingInfoChange", "debugTable", "expand", "containerRef", "usePinToBottom", "handleSelect", "Object", "keys", "map", "rowsById", "React", "div", "ref", "className", "mx", "root", "inputSurface", "style", "width", "getTotalSize", "TableHead", "headers", "getHeaderGroups", "TableBody", "onFocus", "onSelect", "i", "Fragment", "key", "thead", "tr", "margin", "th", "colSpan", "group", "String", "getGroupingValue", "subRows", "TableFoot", "footers", "getFooterGroups", "pre", "code", "JSON", "stringify", "undefined", "useRef", "stickyScrolling", "setStickyScrolling", "container", "current", "handler", "bottom", "scrollHeight", "scrollTop", "clientHeight", "addEventListener", "removeEventListener", "scroll", "top", "border", "headerGroup", "column", "columnDef", "getSize", "groupBorder", "isPlaceholder", "flexRender", "getContext", "resizable", "getIsResizing", "transform", "deltaOffset", "onMouseDown", "getResizeHandler", "onTouchStart", "keyAccessor", "tbody", "onClick", "role", "td", "button", "height", "onBlur", "onKeyDown", "event", "getVisibleCells", "cell", "tfoot", "footerGroup", "CaretDown", "React", "useCallback", "useState", "Popover", "useTranslation", "PopoverCombobox", "descriptionText", "getSize", "mx", "staticPlaceholderText", "translationKey", "initialItems", "model", "value", "getId", "label", "getText", "data", "ComboboxCell", "onValueChange", "t", "useTranslation", "translationKey", "items", "setItems", "useState", "loading", "setLoading", "searchInputValue", "setSearchInputValue", "handleSearchInputValueChange", "text", "query", "reduce", "acc", "item", "handleValueChange", "useCallback", "id", "React", "PopoverCombobox", "Root", "placeholder", "Trigger", "variant", "classNames", "span", "className", "mx", "staticPlaceholderText", "CaretDown", "weight", "getSize", "Content", "shouldFilter", "Input", "List", "length", "p", "descriptionText", "Empty", "Object", "entries", "map", "Item", "key", "onSelect", "Popover", "Arrow", "useFocusFinders", "Check", "ClipboardText", "X", "createColumnHelper", "format", "formatDistanceToNow", "defaultsDeep", "React", "useRef", "useState", "Input", "Tooltip", "getSize", "mx", "stripUndefinedValues", "findNextFocusable", "findFirstFocusable", "container", "next", "tagName", "nextElementSibling", "nextSibling", "createColumnBuilder", "helper", "createColumnHelper", "builder", "ColumnBuilder", "defaults", "options", "sources", "stripUndefinedValues", "defaultsDeep", "select", "label", "className", "model", "onUpdate", "props", "minSize", "header", "column", "React", "div", "id", "cell", "ComboboxCell", "value", "getValue", "onValueChange", "row", "original", "mx", "getText", "string", "initialValue", "setValue", "useState", "inputRef", "useRef", "useFocusFinders", "handleSave", "focusNext", "rowElement", "current", "parentElement", "setTimeout", "focus", "handleCancel", "rows", "table", "getRowModel", "flatRows", "columns", "getVisibleFlatColumns", "placeholder", "index", "length", "Input", "Root", "TextInput", "ref", "variant", "undefined", "classNames", "onBlur", "onChange", "event", "target", "onKeyDown", "key", "number", "digits", "size", "text", "setText", "handleEdit", "String", "trim", "Number", "NaN", "isNaN", "autoFocus", "onClick", "toLocaleString", "minimumFractionDigits", "maximumFractionDigits", "date", "format", "formatSpec", "relative", "str", "formatDistanceToNow", "addSuffix", "toISOString", "err", "console", "log", "tooltip", "element", "truncate", "Tooltip", "Provider", "Trigger", "asChild", "Content", "side", "Arrow", "ClipboardText", "ev", "stopPropagation", "navigator", "clipboard", "writeText", "toHex", "checkbox", "Checkbox", "disabled", "checked", "onCheckedChange", "icon", "on", "off", "IconOn", "Icon", "Check", "IconOff", "X", "getSize"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"packages/ui/react-ui-table/src/schema.ts":{"bytes":1836,"imports":[],"format":"esm"},"packages/ui/react-ui-table/src/components/ColumnMenu.tsx":{"bytes":28711,"imports":[{"path":"@phosphor-icons/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-table/src/schema.ts","kind":"import-statement","original":"../schema"}],"format":"esm"},"packages/ui/react-ui-table/src/theme.ts":{"bytes":4180,"imports":[{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-table/src/components/Table.tsx":{"bytes":50838,"imports":[{"path":"@tanstack/react-table","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-table/src/theme.ts","kind":"import-statement","original":"../theme"}],"format":"esm"},"packages/ui/react-ui-table/src/components/index.ts":{"bytes":
|
|
1
|
+
{"inputs":{"packages/ui/react-ui-table/src/schema.ts":{"bytes":1836,"imports":[],"format":"esm"},"packages/ui/react-ui-table/src/components/ColumnMenu.tsx":{"bytes":28711,"imports":[{"path":"@phosphor-icons/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-table/src/schema.ts","kind":"import-statement","original":"../schema"}],"format":"esm"},"packages/ui/react-ui-table/src/theme.ts":{"bytes":4180,"imports":[{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-table/src/components/Table.tsx":{"bytes":50838,"imports":[{"path":"@tanstack/react-table","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-table/src/theme.ts","kind":"import-statement","original":"../theme"}],"format":"esm"},"packages/ui/react-ui-table/src/translations.ts":{"bytes":990,"imports":[],"format":"esm"},"packages/ui/react-ui-table/src/components/ComboboxCell.tsx":{"bytes":11462,"imports":[{"path":"@phosphor-icons/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-searchlist","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-table/src/translations.ts","kind":"import-statement","original":"../translations"}],"format":"esm"},"packages/ui/react-ui-table/src/components/index.ts":{"bytes":664,"imports":[{"path":"packages/ui/react-ui-table/src/components/ColumnMenu.tsx","kind":"import-statement","original":"./ColumnMenu"},{"path":"packages/ui/react-ui-table/src/components/Table.tsx","kind":"import-statement","original":"./Table"},{"path":"packages/ui/react-ui-table/src/components/ComboboxCell.tsx","kind":"import-statement","original":"./ComboboxCell"}],"format":"esm"},"packages/ui/react-ui-table/src/helpers.tsx":{"bytes":40972,"imports":[{"path":"@fluentui/react-tabster","kind":"import-statement","external":true},{"path":"@phosphor-icons/react","kind":"import-statement","external":true},{"path":"@tanstack/react-table","kind":"import-statement","external":true},{"path":"date-fns/format","kind":"import-statement","external":true},{"path":"date-fns/formatDistanceToNow","kind":"import-statement","external":true},{"path":"lodash.defaultsdeep","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-table/src/components/index.ts","kind":"import-statement","original":"./components"}],"format":"esm"},"packages/ui/react-ui-table/src/types.ts":{"bytes":1522,"imports":[],"format":"esm"},"packages/ui/react-ui-table/src/index.ts":{"bytes":803,"imports":[{"path":"packages/ui/react-ui-table/src/components/index.ts","kind":"import-statement","original":"./components"},{"path":"packages/ui/react-ui-table/src/helpers.tsx","kind":"import-statement","original":"./helpers"},{"path":"packages/ui/react-ui-table/src/schema.ts","kind":"import-statement","original":"./schema"},{"path":"packages/ui/react-ui-table/src/theme.ts","kind":"import-statement","original":"./theme"},{"path":"packages/ui/react-ui-table/src/types.ts","kind":"import-statement","original":"./types"}],"format":"esm"}},"outputs":{"packages/ui/react-ui-table/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":74172},"packages/ui/react-ui-table/dist/lib/browser/index.mjs":{"imports":[{"path":"@phosphor-icons/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"@tanstack/react-table","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@phosphor-icons/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-searchlist","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@fluentui/react-tabster","kind":"import-statement","external":true},{"path":"@phosphor-icons/react","kind":"import-statement","external":true},{"path":"@tanstack/react-table","kind":"import-statement","external":true},{"path":"date-fns/format","kind":"import-statement","external":true},{"path":"date-fns/formatDistanceToNow","kind":"import-statement","external":true},{"path":"lodash.defaultsdeep","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["ColumnBuilder","ColumnMenu","ColumnPanel","ComboboxCell","Table","columnTypes","createColumnBuilder","defaultTableSlots","updateSelection"],"entryPoint":"packages/ui/react-ui-table/src/index.ts","inputs":{"packages/ui/react-ui-table/src/components/ColumnMenu.tsx":{"bytesInOutput":7708},"packages/ui/react-ui-table/src/schema.ts":{"bytesInOutput":224},"packages/ui/react-ui-table/src/components/index.ts":{"bytesInOutput":0},"packages/ui/react-ui-table/src/components/Table.tsx":{"bytesInOutput":11866},"packages/ui/react-ui-table/src/theme.ts":{"bytesInOutput":542},"packages/ui/react-ui-table/src/components/ComboboxCell.tsx":{"bytesInOutput":3039},"packages/ui/react-ui-table/src/translations.ts":{"bytesInOutput":162},"packages/ui/react-ui-table/src/index.ts":{"bytesInOutput":0},"packages/ui/react-ui-table/src/helpers.tsx":{"bytesInOutput":10021}},"bytes":34303}}}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type RowData } from '@tanstack/react-table';
|
|
2
|
+
import { type SelectQueryModel } from '../helpers';
|
|
3
|
+
export type ComboboxCellItems<TData extends RowData> = Record<string, {
|
|
4
|
+
label: string;
|
|
5
|
+
data: TData;
|
|
6
|
+
}>;
|
|
7
|
+
export declare const ComboboxCell: <TData extends unknown>({ model, value, onValueChange, }: {
|
|
8
|
+
model: SelectQueryModel<TData>;
|
|
9
|
+
value: TData;
|
|
10
|
+
onValueChange: (value: TData) => void;
|
|
11
|
+
}) => JSX.Element;
|
|
12
|
+
//# sourceMappingURL=ComboboxCell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComboboxCell.d.ts","sourceRoot":"","sources":["../../../../src/components/ComboboxCell.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAOrD,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGnD,MAAM,MAAM,iBAAiB,CAAC,KAAK,SAAS,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAStG,eAAO,MAAM,YAAY;;;qCAOU,IAAI;iBAiEtC,CAAC"}
|
|
@@ -4,6 +4,7 @@ import { type TableColumnDef } from '../types';
|
|
|
4
4
|
type Item = {
|
|
5
5
|
publicKey: PublicKey;
|
|
6
6
|
name: string;
|
|
7
|
+
company?: string;
|
|
7
8
|
count?: number;
|
|
8
9
|
started?: Date;
|
|
9
10
|
complete?: boolean;
|
|
@@ -56,9 +57,6 @@ declare const _default: {
|
|
|
56
57
|
};
|
|
57
58
|
};
|
|
58
59
|
decorators: ((Story: any) => JSX.Element)[];
|
|
59
|
-
parameters: {
|
|
60
|
-
layout: string;
|
|
61
|
-
};
|
|
62
60
|
};
|
|
63
61
|
export default _default;
|
|
64
62
|
export declare const Default: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Table.stories.d.ts","sourceRoot":"","sources":["../../../../src/components/Table.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AAOpB,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAMvC,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAK/C,KAAK,IAAI,GAAG;IACV,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;;;;;
|
|
1
|
+
{"version":3,"file":"Table.stories.d.ts","sourceRoot":"","sources":["../../../../src/components/Table.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AAOpB,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAMvC,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAK/C,KAAK,IAAI,GAAG;IACV,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;;;;;4BAgGsB,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAyChB,GAAG;;AA7Cf,wBAmDE;AAEF,eAAO,MAAM,OAAO;;;;;CAKnB,CAAC;AAEF,eAAO,MAAM,SAAS;;;;;CAKrB,CAAC;AAEF,eAAO,MAAM,UAAU;;;;;;;;;CAMtB,CAAC;AAEF,eAAO,MAAM,KAAK;;;;CAIjB,CAAC;AAEF,eAAO,MAAM,OAAO;;CA8BnB,CAAC;AAEF,eAAO,MAAM,QAAQ;;CAmBpB,CAAC;AAEF,eAAO,MAAM,SAAS;;CAwBrB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAIA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAIA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/helpers.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAwB,KAAK,IAAI,EAAK,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAsB,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAM1G,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/helpers.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translations.d.ts","sourceRoot":"","sources":["../../../src/translations.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc,UAAU,CAAC;;;;;;;;AAEtC,wBAQE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-table",
|
|
3
|
-
"version": "0.3.7-main.
|
|
3
|
+
"version": "0.3.7-main.ec7f1fc",
|
|
4
4
|
"description": "A table component.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -20,13 +20,14 @@
|
|
|
20
20
|
"@tanstack/react-table": "^8.9.3",
|
|
21
21
|
"date-fns": "^2.29.3",
|
|
22
22
|
"lodash.defaultsdeep": "^4.6.1",
|
|
23
|
-
"@dxos/invariant": "0.3.7-main.
|
|
24
|
-
"@dxos/
|
|
25
|
-
"@dxos/
|
|
26
|
-
"@dxos/
|
|
27
|
-
"@dxos/react-ui
|
|
28
|
-
"@dxos/react-ui-
|
|
29
|
-
"@dxos/
|
|
23
|
+
"@dxos/invariant": "0.3.7-main.ec7f1fc",
|
|
24
|
+
"@dxos/async": "0.3.7-main.ec7f1fc",
|
|
25
|
+
"@dxos/keys": "0.3.7-main.ec7f1fc",
|
|
26
|
+
"@dxos/react-ui-searchlist": "0.3.7-main.ec7f1fc",
|
|
27
|
+
"@dxos/react-ui": "0.3.7-main.ec7f1fc",
|
|
28
|
+
"@dxos/react-ui-types": "0.3.7-main.ec7f1fc",
|
|
29
|
+
"@dxos/react-ui-theme": "0.3.7-main.ec7f1fc",
|
|
30
|
+
"@dxos/util": "0.3.7-main.ec7f1fc"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
33
|
"@faker-js/faker": "^8.0.2",
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
"react-dom": "^18.2.0",
|
|
41
42
|
"vite": "^4.3.9",
|
|
42
43
|
"vite-plugin-turbosnap": "^1.0.2",
|
|
43
|
-
"@dxos/react-ui-theme": "0.3.7-main.
|
|
44
|
+
"@dxos/react-ui-theme": "0.3.7-main.ec7f1fc"
|
|
44
45
|
},
|
|
45
46
|
"peerDependencies": {
|
|
46
47
|
"@phosphor-icons/react": "^2.0.5",
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { CaretDown } from '@phosphor-icons/react';
|
|
6
|
+
import { type RowData } from '@tanstack/react-table';
|
|
7
|
+
import React, { useCallback, useState } from 'react';
|
|
8
|
+
|
|
9
|
+
import { Popover, useTranslation } from '@dxos/react-ui';
|
|
10
|
+
import { PopoverCombobox } from '@dxos/react-ui-searchlist';
|
|
11
|
+
import { descriptionText, getSize, mx, staticPlaceholderText } from '@dxos/react-ui-theme';
|
|
12
|
+
|
|
13
|
+
import { type SelectQueryModel } from '../helpers';
|
|
14
|
+
import { translationKey } from '../translations';
|
|
15
|
+
|
|
16
|
+
export type ComboboxCellItems<TData extends RowData> = Record<string, { label: string; data: TData }>;
|
|
17
|
+
|
|
18
|
+
const initialItems = <TData extends RowData>(model: SelectQueryModel<TData>, value?: TData) =>
|
|
19
|
+
value
|
|
20
|
+
? {
|
|
21
|
+
[model.getId(value)]: { label: model.getText(value), data: value },
|
|
22
|
+
}
|
|
23
|
+
: {};
|
|
24
|
+
|
|
25
|
+
export const ComboboxCell = <TData extends RowData>({
|
|
26
|
+
model,
|
|
27
|
+
value,
|
|
28
|
+
onValueChange,
|
|
29
|
+
}: {
|
|
30
|
+
model: SelectQueryModel<TData>;
|
|
31
|
+
value: TData;
|
|
32
|
+
onValueChange: (value: TData) => void;
|
|
33
|
+
}) => {
|
|
34
|
+
const { t } = useTranslation(translationKey);
|
|
35
|
+
const [items, setItems] = useState<ComboboxCellItems<TData>>(initialItems(model, value));
|
|
36
|
+
const [loading, setLoading] = useState(false);
|
|
37
|
+
const [searchInputValue, setSearchInputValue] = useState('');
|
|
38
|
+
const handleSearchInputValueChange = async (text?: string) => {
|
|
39
|
+
setSearchInputValue(text ?? '');
|
|
40
|
+
setLoading(true);
|
|
41
|
+
const items = await model.query(text);
|
|
42
|
+
setItems(
|
|
43
|
+
items.reduce((acc: ComboboxCellItems<TData>, item) => {
|
|
44
|
+
acc[model.getId(item)] = {
|
|
45
|
+
label: model.getText(item),
|
|
46
|
+
data: item,
|
|
47
|
+
};
|
|
48
|
+
return acc;
|
|
49
|
+
}, initialItems(model, value)),
|
|
50
|
+
);
|
|
51
|
+
setLoading(false);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const handleValueChange = useCallback(
|
|
55
|
+
(id: string) => {
|
|
56
|
+
onValueChange(items[id]?.data);
|
|
57
|
+
},
|
|
58
|
+
[items, onValueChange],
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<PopoverCombobox.Root placeholder={t('no selection label')}>
|
|
63
|
+
<PopoverCombobox.Trigger variant='ghost' classNames='is-full'>
|
|
64
|
+
{value ? (
|
|
65
|
+
<>
|
|
66
|
+
<span
|
|
67
|
+
className={mx('font-normal text-start flex-1 min-is-0 truncate mie-2', !value && staticPlaceholderText)}
|
|
68
|
+
>
|
|
69
|
+
{model.getText(value)}
|
|
70
|
+
</span>
|
|
71
|
+
<CaretDown weight='bold' className={getSize(3)} />
|
|
72
|
+
</>
|
|
73
|
+
) : null}
|
|
74
|
+
</PopoverCombobox.Trigger>
|
|
75
|
+
<PopoverCombobox.Content shouldFilter={false} classNames='is-[--radix-popover-trigger-width]'>
|
|
76
|
+
<PopoverCombobox.Input value={searchInputValue} onValueChange={handleSearchInputValueChange} />
|
|
77
|
+
<PopoverCombobox.List>
|
|
78
|
+
{searchInputValue.length < 1 ? (
|
|
79
|
+
<p className={mx('text-center', descriptionText)}>Start typing to search</p>
|
|
80
|
+
) : loading ? (
|
|
81
|
+
<p className={mx('text-center', descriptionText)}>Searching…</p>
|
|
82
|
+
) : (
|
|
83
|
+
<>
|
|
84
|
+
<PopoverCombobox.Empty classNames={['text-center', descriptionText]}>No results</PopoverCombobox.Empty>
|
|
85
|
+
{Object.entries(items).map(([id, { label }]) => (
|
|
86
|
+
<PopoverCombobox.Item key={id} value={id} onSelect={handleValueChange} classNames='truncate'>
|
|
87
|
+
{label}
|
|
88
|
+
</PopoverCombobox.Item>
|
|
89
|
+
))}
|
|
90
|
+
</>
|
|
91
|
+
)}
|
|
92
|
+
</PopoverCombobox.List>
|
|
93
|
+
<Popover.Arrow />
|
|
94
|
+
</PopoverCombobox.Content>
|
|
95
|
+
</PopoverCombobox.Root>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
@@ -14,7 +14,7 @@ import { DensityProvider } from '@dxos/react-ui';
|
|
|
14
14
|
import { range } from '@dxos/util';
|
|
15
15
|
|
|
16
16
|
import { Table } from './Table';
|
|
17
|
-
import { createColumnBuilder, type ValueUpdater } from '../helpers';
|
|
17
|
+
import { createColumnBuilder, type SelectQueryModel, type ValueUpdater } from '../helpers';
|
|
18
18
|
import { type TableColumnDef } from '../types';
|
|
19
19
|
|
|
20
20
|
// TODO(burdon): Header menu builder.
|
|
@@ -23,11 +23,13 @@ import { type TableColumnDef } from '../types';
|
|
|
23
23
|
type Item = {
|
|
24
24
|
publicKey: PublicKey;
|
|
25
25
|
name: string;
|
|
26
|
+
company?: string;
|
|
26
27
|
count?: number;
|
|
27
28
|
started?: Date;
|
|
28
29
|
complete?: boolean;
|
|
29
30
|
};
|
|
30
31
|
|
|
32
|
+
// TODO(thure): …y’all okay?
|
|
31
33
|
faker.seed(911);
|
|
32
34
|
|
|
33
35
|
const createItems = (count: number) =>
|
|
@@ -46,6 +48,28 @@ const updateItems = <TValue = any,>(items: Item[], key: PublicKey, id: string, v
|
|
|
46
48
|
return items.map((item) => (item.publicKey.equals(key) ? { ...item, [id]: value } : item));
|
|
47
49
|
};
|
|
48
50
|
|
|
51
|
+
const tableStorySelectItems: Record<string, Item> = range(128).reduce((acc: Record<string, Item>, _i) => {
|
|
52
|
+
const id = PublicKey.random();
|
|
53
|
+
acc[id.toHex()] = {
|
|
54
|
+
publicKey: id,
|
|
55
|
+
name: faker.company.name(),
|
|
56
|
+
};
|
|
57
|
+
return acc;
|
|
58
|
+
}, {});
|
|
59
|
+
|
|
60
|
+
const timeout = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
61
|
+
|
|
62
|
+
const tableStorySelectModel: SelectQueryModel<Item> = {
|
|
63
|
+
getId: (object) => object?.publicKey?.toHex() ?? 'never',
|
|
64
|
+
getText: (object) => object?.name ?? 'never',
|
|
65
|
+
query: async (search: string) => {
|
|
66
|
+
await timeout(400);
|
|
67
|
+
return Object.values(tableStorySelectItems).filter((item) => {
|
|
68
|
+
return item.name.toLowerCase().includes(search.toLowerCase());
|
|
69
|
+
});
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
49
73
|
const { helper, builder } = createColumnBuilder<Item>();
|
|
50
74
|
const columns = (onUpdate?: ValueUpdater<Item, any>): TableColumnDef<Item, any>[] => [
|
|
51
75
|
helper.accessor(
|
|
@@ -62,6 +86,14 @@ const columns = (onUpdate?: ValueUpdater<Item, any>): TableColumnDef<Item, any>[
|
|
|
62
86
|
'name',
|
|
63
87
|
builder.string({ onUpdate, meta: { expand: true }, footer: (props) => props.table.getRowModel().rows.length }),
|
|
64
88
|
),
|
|
89
|
+
helper.accessor(
|
|
90
|
+
'company',
|
|
91
|
+
builder.select({
|
|
92
|
+
label: 'Company',
|
|
93
|
+
model: tableStorySelectModel,
|
|
94
|
+
onUpdate,
|
|
95
|
+
}),
|
|
96
|
+
),
|
|
65
97
|
helper.accessor('started', builder.date({ relative: true, meta: { resizable: true } })),
|
|
66
98
|
helper.accessor(
|
|
67
99
|
'count',
|
|
@@ -133,18 +165,11 @@ export default {
|
|
|
133
165
|
},
|
|
134
166
|
decorators: [
|
|
135
167
|
(Story: any) => (
|
|
136
|
-
<
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
<Story />
|
|
140
|
-
</DensityProvider>
|
|
141
|
-
</div>
|
|
142
|
-
</div>
|
|
168
|
+
<DensityProvider density='fine'>
|
|
169
|
+
<Story />
|
|
170
|
+
</DensityProvider>
|
|
143
171
|
),
|
|
144
172
|
],
|
|
145
|
-
parameters: {
|
|
146
|
-
layout: 'fullscreen',
|
|
147
|
-
},
|
|
148
173
|
};
|
|
149
174
|
|
|
150
175
|
export const Default = {
|
package/src/components/index.ts
CHANGED
package/src/helpers.tsx
CHANGED
|
@@ -8,13 +8,15 @@ import { createColumnHelper, type ColumnDef, type ColumnMeta, type RowData } fro
|
|
|
8
8
|
import format from 'date-fns/format';
|
|
9
9
|
import formatDistanceToNow from 'date-fns/formatDistanceToNow';
|
|
10
10
|
import defaultsDeep from 'lodash.defaultsdeep';
|
|
11
|
-
import React, {
|
|
11
|
+
import React, { useRef, useState } from 'react';
|
|
12
12
|
|
|
13
13
|
import { type PublicKey } from '@dxos/keys';
|
|
14
|
-
import {
|
|
14
|
+
import { Input, Tooltip } from '@dxos/react-ui';
|
|
15
15
|
import { getSize, mx } from '@dxos/react-ui-theme';
|
|
16
16
|
import { stripUndefinedValues } from '@dxos/util';
|
|
17
17
|
|
|
18
|
+
import { ComboboxCell } from './components';
|
|
19
|
+
|
|
18
20
|
// TODO(burdon): Factor out hack to find next focusable element (extend useFocusFinders)?
|
|
19
21
|
const findNextFocusable = (
|
|
20
22
|
findFirstFocusable: (container: HTMLElement) => HTMLElement | null | undefined,
|
|
@@ -94,51 +96,6 @@ const defaults = <TData extends RowData, TValue>(
|
|
|
94
96
|
return stripUndefinedValues(defaultsDeep({}, options, ...sources));
|
|
95
97
|
};
|
|
96
98
|
|
|
97
|
-
/**
|
|
98
|
-
* Lazy cell selector (click to activate).
|
|
99
|
-
*/
|
|
100
|
-
const CellSelector = <TData extends RowData>({
|
|
101
|
-
model,
|
|
102
|
-
value: _value,
|
|
103
|
-
onUpdate,
|
|
104
|
-
}: {
|
|
105
|
-
model: SelectQueryModel<TData>;
|
|
106
|
-
value: TData;
|
|
107
|
-
onUpdate: (value: TData) => void;
|
|
108
|
-
}) => {
|
|
109
|
-
const [edit, setEdit] = useState(false);
|
|
110
|
-
const [value, setValue] = useState<ComboBoxItem>();
|
|
111
|
-
useEffect(() => setValue(_value ? { id: model.getId(_value), label: model.getText(_value) } : undefined), [_value]);
|
|
112
|
-
const [items, setItems] = useState<ComboBoxItem[]>([]);
|
|
113
|
-
const handleUpdate = async (text?: string) => {
|
|
114
|
-
const items = await model.query(text);
|
|
115
|
-
setItems(items.map((item) => ({ id: model.getId(item), label: model.getText(item), data: item })));
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
if (!edit) {
|
|
119
|
-
const text = _value ? model.getText(_value) : undefined;
|
|
120
|
-
return (
|
|
121
|
-
// TODO(burdon): Hack to prevent div from collapsing.
|
|
122
|
-
<div className={mx('w-full px-2', !text && 'opacity-0')} onClick={() => setEdit(true)}>
|
|
123
|
-
{text ?? '-'}
|
|
124
|
-
</div>
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return (
|
|
129
|
-
<ComboBox.Root items={items} value={value} onChange={(value) => onUpdate(value?.data)} onInputChange={handleUpdate}>
|
|
130
|
-
<ComboBox.Input />
|
|
131
|
-
<ComboBox.Content>
|
|
132
|
-
{items.map((item) => (
|
|
133
|
-
<ComboBox.Item key={item.id} item={item}>
|
|
134
|
-
{item.label}
|
|
135
|
-
</ComboBox.Item>
|
|
136
|
-
))}
|
|
137
|
-
</ComboBox.Content>
|
|
138
|
-
</ComboBox.Root>
|
|
139
|
-
);
|
|
140
|
-
};
|
|
141
|
-
|
|
142
99
|
/**
|
|
143
100
|
* Util to create column definitions.
|
|
144
101
|
*/
|
|
@@ -155,10 +112,10 @@ export class ColumnBuilder<TData extends RowData> {
|
|
|
155
112
|
cell:
|
|
156
113
|
model && onUpdate
|
|
157
114
|
? (cell) => (
|
|
158
|
-
<
|
|
115
|
+
<ComboboxCell<any>
|
|
159
116
|
model={model}
|
|
160
117
|
value={cell.getValue()}
|
|
161
|
-
|
|
118
|
+
onValueChange={(value) => onUpdate?.(cell.row.original, cell.column.id, value)}
|
|
162
119
|
/>
|
|
163
120
|
)
|
|
164
121
|
: (cell) => {
|