@crisp-ui-kit/crisp 0.54.10 → 0.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/datatable/datatable.js +249 -46
- package/dist/cjs/components/datatable/datatable.recipe.js +24 -0
- package/dist/cjs/components/resizablepanel/resizablepanel.js +10 -1
- package/dist/cjs/components/table/table.js +8 -1
- package/dist/cjs/components/tabletoolbar/tabletoolbar.chrome.js +25 -2
- package/dist/cjs/components/tabletoolbar/tabletoolbar.js +176 -43
- package/dist/cjs/components/tabletoolbar/tabletoolbar.recipe.js +28 -9
- package/dist/cjs/index.js +0 -2
- package/dist/cjs/product/recordpage/column.js +19 -0
- package/dist/cjs/product/recordpage/index.js +6 -1
- package/dist/cjs/product/recordpage/recordpage.js +25 -8
- package/dist/cjs/product/recordpage/test-fixtures.js +55 -0
- package/dist/cjs/product/savedviews/savedviews.recipe.js +13 -11
- package/dist/datatable.css +14 -0
- package/dist/datatable.layered.css +14 -0
- package/dist/esm/components/datatable/datatable.js +250 -47
- package/dist/esm/components/datatable/datatable.recipe.js +24 -0
- package/dist/esm/components/resizablepanel/resizablepanel.js +10 -1
- package/dist/esm/components/table/table.js +8 -1
- package/dist/esm/components/tabletoolbar/tabletoolbar.chrome.js +25 -2
- package/dist/esm/components/tabletoolbar/tabletoolbar.js +177 -44
- package/dist/esm/components/tabletoolbar/tabletoolbar.recipe.js +28 -9
- package/dist/esm/index.js +0 -2
- package/dist/esm/product/recordpage/column.js +16 -0
- package/dist/esm/product/recordpage/index.js +2 -0
- package/dist/esm/product/recordpage/recordpage.js +22 -5
- package/dist/esm/product/recordpage/test-fixtures.js +52 -0
- package/dist/esm/product/savedviews/savedviews.recipe.js +13 -11
- package/dist/savedviews.css +6 -18
- package/dist/savedviews.layered.css +6 -18
- package/dist/styles.css +43 -276
- package/dist/styles.layered.css +43 -276
- package/dist/tabletoolbar.css +23 -3
- package/dist/tabletoolbar.layered.css +23 -3
- package/dist/types/components/datatable/datatable.d.ts +30 -3
- package/dist/types/components/table/table.d.ts +14 -0
- package/dist/types/components/tabletoolbar/tabletoolbar.d.ts +26 -1
- package/dist/types/index.d.ts +0 -2
- package/dist/types/product/recordpage/column.d.ts +112 -0
- package/dist/types/product/recordpage/index.d.ts +2 -0
- package/dist/types/product/recordpage/recordpage.d.ts +1 -1
- package/dist/types/product/recordpage/test-fixtures.d.ts +3 -0
- package/dist/types/product/recordpanel/recordpanel.d.ts +1 -1
- package/package.json +2 -12
- package/dist/cjs/product/recordstable/company-logos.js +0 -29
- package/dist/cjs/product/recordstable/index.js +0 -13
- package/dist/cjs/product/recordstable/recordstable.js +0 -1357
- package/dist/cjs/product/recordstable/recordstable.recipe.js +0 -175
- package/dist/cjs/product/recordstable/recordstable.tag.js +0 -26
- package/dist/cjs/product/taskstable/index.js +0 -7
- package/dist/cjs/product/taskstable/taskstable.js +0 -27
- package/dist/cjs/product/taskstable/taskstable.recipe.js +0 -56
- package/dist/esm/product/recordstable/company-logos.js +0 -26
- package/dist/esm/product/recordstable/index.js +0 -3
- package/dist/esm/product/recordstable/recordstable.js +0 -1317
- package/dist/esm/product/recordstable/recordstable.recipe.js +0 -172
- package/dist/esm/product/recordstable/recordstable.tag.js +0 -23
- package/dist/esm/product/taskstable/index.js +0 -2
- package/dist/esm/product/taskstable/taskstable.js +0 -24
- package/dist/esm/product/taskstable/taskstable.recipe.js +0 -53
- package/dist/recordstable.css +0 -223
- package/dist/recordstable.d.ts +0 -7
- package/dist/recordstable.layered.css +0 -225
- package/dist/taskstable.css +0 -30
- package/dist/taskstable.d.ts +0 -7
- package/dist/taskstable.layered.css +0 -32
- package/dist/types/product/recordstable/company-logos.d.ts +0 -1
- package/dist/types/product/recordstable/index.d.ts +0 -3
- package/dist/types/product/recordstable/recordstable.d.ts +0 -289
- package/dist/types/product/recordstable/recordstable.recipe.d.ts +0 -5
- package/dist/types/product/recordstable/recordstable.tag.d.ts +0 -15
- package/dist/types/product/taskstable/index.d.ts +0 -2
- package/dist/types/product/taskstable/taskstable.d.ts +0 -54
- package/dist/types/product/taskstable/taskstable.recipe.d.ts +0 -3
- /package/dist/cjs/product/{recordstable → recordpage}/editable-field.js +0 -0
- /package/dist/esm/product/{recordstable → recordpage}/editable-field.js +0 -0
- /package/dist/types/product/{recordstable → recordpage}/editable-field.d.ts +0 -0
|
@@ -40,11 +40,41 @@ exports.TableToolbar = TableToolbar;
|
|
|
40
40
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
41
41
|
const lucide_react_1 = require("lucide-react");
|
|
42
42
|
const React = __importStar(require("react"));
|
|
43
|
+
const react_dom_1 = require("react-dom");
|
|
43
44
|
const core_1 = require("../../core");
|
|
44
45
|
const datepicker_1 = require("../datepicker");
|
|
45
46
|
const menu_1 = require("../menu");
|
|
46
47
|
const select_1 = require("../select");
|
|
47
48
|
const tabletoolbar_recipe_1 = require("./tabletoolbar.recipe");
|
|
49
|
+
// crisp/#766, #772: portals View settings/Import-Export into a
|
|
50
|
+
// consumer-supplied target (e.g. a `<span>` rendered next to `SavedViews`,
|
|
51
|
+
// or another next to the primary action) instead of this toolbar's own row,
|
|
52
|
+
// when one is given -- a plain passthrough otherwise, so the default (no
|
|
53
|
+
// ref given) stays byte-identical to before this existed. Kept outside the
|
|
54
|
+
// main component (no closure over its state) so it's a stable reference
|
|
55
|
+
// across renders.
|
|
56
|
+
//
|
|
57
|
+
// #772 fix: every `.crisp-tabletoolbar-*` chrome rule is nested under this
|
|
58
|
+
// recipe's own root class (`& .crisp-tabletoolbar-tool { ... }`), which
|
|
59
|
+
// compiles to a real CSS descendant combinator -- it needs actual DOM
|
|
60
|
+
// containment under an element carrying that class. A portal target
|
|
61
|
+
// rendered by the CONSUMER, outside this component's own root `<div>`,
|
|
62
|
+
// breaks that containment even though React still considers the portaled
|
|
63
|
+
// content a child for event/context purposes: the classes were still
|
|
64
|
+
// applied, they just matched nothing, so the buttons rendered as unstyled
|
|
65
|
+
// native chrome. Same failure class `select.recipe.ts`'s own doc comment
|
|
66
|
+
// describes for its listbox portal to `document.body`. Fixed the same way
|
|
67
|
+
// `ToolbarTool` (below) already lets a bare `.crisp-tabletoolbar-tool` be
|
|
68
|
+
// used outside an actual `TableToolbar` tree: wrap the portaled content in
|
|
69
|
+
// its own `tabletoolbarRecipe()`-classed span. `display: contents` on that
|
|
70
|
+
// recipe's own base rule means the wrapper contributes no box of its own,
|
|
71
|
+
// so it changes nothing about layout -- only re-establishes the selector
|
|
72
|
+
// match.
|
|
73
|
+
function ViewBarSlot({ target, children, }) {
|
|
74
|
+
return target
|
|
75
|
+
? (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)("span", { className: (0, tabletoolbar_recipe_1.tabletoolbarRecipe)(), children: children }), target)
|
|
76
|
+
: children;
|
|
77
|
+
}
|
|
48
78
|
// #592: shared by every direction-bearing ChevronRight usage below (the
|
|
49
79
|
// field picker's own disclosure chevron, a flattened search result's
|
|
50
80
|
// breadcrumb separator, and a filter chip's own breadcrumb separator) so
|
|
@@ -338,7 +368,7 @@ function applySorts(rows, sorts, get = (row, key) => row[key]) {
|
|
|
338
368
|
* this (Sort: Due date/Assignee/Creation date; Filter: Assignee/Record/
|
|
339
369
|
* Created by), which one shared list can't reproduce.
|
|
340
370
|
*/
|
|
341
|
-
function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: filterColumnsProp, sorts: sortsProp, defaultSorts, onSortsChange, filters: filtersProp, defaultFilters, onFiltersChange, count, children, helpHref, className, sortLabel: sortLabelProp, filterLabel: filterLabelProp, reorderSortLabel: reorderSortLabelProp, noSortsLabel: noSortsLabelProp, addSortLabel: addSortLabelProp, learnSortingLabel: learnSortingLabelProp, selectConditionLabel: selectConditionLabelProp, sortFieldLabel: sortFieldLabelProp, sortDirectionLabel: sortDirectionLabelProp, removeSortLabel: removeSortLabelProp, filterFieldLabel: filterFieldLabelProp, filterFieldPlaceholder: filterFieldPlaceholderProp, filterValuePlaceholder: filterValuePlaceholderProp, filterOptionsLabel: filterOptionsLabelProp, deleteFilterLabel: deleteFilterLabelProp, ascendingLabel: ascendingLabelProp, descendingLabel: descendingLabelProp, sortTriggerLabel, filterTriggerLabel, inline, showSort = true, showViewSettings = true, viewColumns: viewColumnsProp, shownKeys: shownKeysProp, defaultShownKeys, onShownKeysChange, viewSettingsLabel: viewSettingsLabelProp, reorderAttributeLabel: reorderAttributeLabelProp, hideAttributeLabel, addAttributeToViewLabel: addAttributeToViewLabelProp, searchAttributesPlaceholder: searchAttributesPlaceholderProp, importExportLabel: importExportLabelProp, onImportCsv, onExportCsv, onExportExcel, importExportHelpHref, importCsvLabel: importCsvLabelProp, exportCsvLabel: exportCsvLabelProp, exportExcelLabel: exportExcelLabelProp, learnImportExportLabel: learnImportExportLabelProp, backLabel: backLabelProp, nestedFieldPlaceholder, ...rest }) {
|
|
371
|
+
function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: filterColumnsProp, sorts: sortsProp, defaultSorts, onSortsChange, filters: filtersProp, defaultFilters, onFiltersChange, count, children, helpHref, className, sortLabel: sortLabelProp, filterLabel: filterLabelProp, reorderSortLabel: reorderSortLabelProp, noSortsLabel: noSortsLabelProp, addSortLabel: addSortLabelProp, learnSortingLabel: learnSortingLabelProp, selectConditionLabel: selectConditionLabelProp, sortFieldLabel: sortFieldLabelProp, sortDirectionLabel: sortDirectionLabelProp, removeSortLabel: removeSortLabelProp, filterFieldLabel: filterFieldLabelProp, filterFieldPlaceholder: filterFieldPlaceholderProp, filterValuePlaceholder: filterValuePlaceholderProp, filterOptionsLabel: filterOptionsLabelProp, deleteFilterLabel: deleteFilterLabelProp, ascendingLabel: ascendingLabelProp, descendingLabel: descendingLabelProp, sortTriggerLabel, filterTriggerLabel, inline, showSort = true, showViewSettings = true, viewSettingsRef, importExportRef, viewColumns: viewColumnsProp, shownKeys: shownKeysProp, defaultShownKeys, onShownKeysChange, viewSettingsLabel: viewSettingsLabelProp, reorderAttributeLabel: reorderAttributeLabelProp, hideAttributeLabel, addAttributeToViewLabel: addAttributeToViewLabelProp, searchAttributesPlaceholder: searchAttributesPlaceholderProp, importExportLabel: importExportLabelProp, onImportCsv, onExportCsv, onExportExcel, importExportHelpHref, importCsvLabel: importCsvLabelProp, exportCsvLabel: exportCsvLabelProp, exportExcelLabel: exportExcelLabelProp, learnImportExportLabel: learnImportExportLabelProp, backLabel: backLabelProp, nestedFieldPlaceholder, ...rest }) {
|
|
342
372
|
// crisp/#471: an explicit prop always wins; missing, it reads the nearest
|
|
343
373
|
// CrispMessagesProvider's translation of the English default below, or
|
|
344
374
|
// that default itself with no provider — unchanged from before this
|
|
@@ -408,6 +438,25 @@ function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: fi
|
|
|
408
438
|
setShownKeysState(next);
|
|
409
439
|
onShownKeysChange?.(next);
|
|
410
440
|
};
|
|
441
|
+
// crisp/#766: a ref's `.current` is null during THIS render (a ref only
|
|
442
|
+
// attaches during commit, and the consumer's own target element may not
|
|
443
|
+
// even exist in the DOM yet on first paint) -- an effect after mount picks
|
|
444
|
+
// it up and re-renders once, the same one-render-late pattern the floating
|
|
445
|
+
// popovers elsewhere in this file already use for a portal target.
|
|
446
|
+
const [viewSettingsTarget, setViewSettingsTarget] = React.useState(null);
|
|
447
|
+
React.useEffect(() => {
|
|
448
|
+
setViewSettingsTarget(viewSettingsRef?.current ?? null);
|
|
449
|
+
}, [viewSettingsRef]);
|
|
450
|
+
const [importExportTarget, setImportExportTarget] = React.useState(null);
|
|
451
|
+
React.useEffect(() => {
|
|
452
|
+
setImportExportTarget(importExportRef?.current ?? null);
|
|
453
|
+
}, [importExportRef]);
|
|
454
|
+
const rootRef = React.useRef(null);
|
|
455
|
+
const viewSettingsTriggerRef = React.useRef(null);
|
|
456
|
+
const viewSettingsContentRef = React.useRef(null);
|
|
457
|
+
const [viewSettingsPos, setViewSettingsPos] = React.useState({});
|
|
458
|
+
const importExportTriggerRef = React.useRef(null);
|
|
459
|
+
const [importExportPos, setImportExportPos] = React.useState({});
|
|
411
460
|
const [openMenu, setOpenMenu] = React.useState(null);
|
|
412
461
|
const [dragSort, setDragSort] = React.useState(null);
|
|
413
462
|
const [filterQuery, setFilterQuery] = React.useState("");
|
|
@@ -435,6 +484,65 @@ function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: fi
|
|
|
435
484
|
// built here -- hiding an attribute is a trailing control instead, see
|
|
436
485
|
// the hide button below).
|
|
437
486
|
const [addingAttribute, setAddingAttribute] = React.useState(false);
|
|
487
|
+
// crisp/#807: `viewSettingsRef`/`importExportRef` (#766) relocate the
|
|
488
|
+
// TRIGGER out of this toolbar's own row, but their POPOVERS stayed
|
|
489
|
+
// `position: absolute` inside the (now relocated) trigger's own
|
|
490
|
+
// `.crisp-tabletoolbar-toolgroup` -- correct chrome-wise (#772 already
|
|
491
|
+
// fixed that), but its stacking is trapped inside whatever DOM branch the
|
|
492
|
+
// consumer's own `viewSettingsRef` slot lives in. A consumer header
|
|
493
|
+
// sitting in an EARLIER sibling branch than the toolbar/grid below it
|
|
494
|
+
// (GRC's own layout) has that later branch simply paint over the popover
|
|
495
|
+
// regardless of its own z-index: 30, because z-index only orders siblings
|
|
496
|
+
// WITHIN the same stacking context, and the two branches aren't one.
|
|
497
|
+
// Fixed the same way `Menu`/`Select`/`Popover` already solve this: the
|
|
498
|
+
// popover content itself portals to `document.body` (`FloatingPortal`),
|
|
499
|
+
// positioned with `placeFloating` against the trigger's own rect (a real
|
|
500
|
+
// `position: fixed` box, anchored by viewport coordinates, escapes ANY
|
|
501
|
+
// ancestor's stacking context) -- not just relocated alongside the
|
|
502
|
+
// trigger. Wrapped in its own `tabletoolbarRecipe()` span (the same
|
|
503
|
+
// reason `ViewBarSlot` wraps the trigger) so every nested
|
|
504
|
+
// `.crisp-tabletoolbar-*` class inside the popover still resolves once
|
|
505
|
+
// portaled outside the toolbar's own root. Sort/Filter's own popovers
|
|
506
|
+
// are untouched -- they never relocate, so they were never trapped.
|
|
507
|
+
const placeViewSettingsMenu = () => {
|
|
508
|
+
const rect = viewSettingsTriggerRef.current?.getBoundingClientRect();
|
|
509
|
+
if (!rect)
|
|
510
|
+
return;
|
|
511
|
+
const { style } = (0, core_1.placeFloating)({
|
|
512
|
+
rect,
|
|
513
|
+
gap: 4,
|
|
514
|
+
flipBelow: 280,
|
|
515
|
+
anchor: viewSettingsTriggerRef.current,
|
|
516
|
+
});
|
|
517
|
+
setViewSettingsPos(style);
|
|
518
|
+
};
|
|
519
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: reposition each time it opens (and when its own screen changes, since the two screens differ in height)
|
|
520
|
+
React.useLayoutEffect(() => {
|
|
521
|
+
if (openMenu === "viewsettings")
|
|
522
|
+
placeViewSettingsMenu();
|
|
523
|
+
}, [openMenu, addingAttribute]);
|
|
524
|
+
React.useEffect(() => {
|
|
525
|
+
if (openMenu !== "viewsettings" || !viewSettingsContentRef.current)
|
|
526
|
+
return;
|
|
527
|
+
return (0, core_1.registerFloatingLayer)(viewSettingsContentRef.current);
|
|
528
|
+
}, [openMenu]);
|
|
529
|
+
const placeImportExportMenu = () => {
|
|
530
|
+
const rect = importExportTriggerRef.current?.getBoundingClientRect();
|
|
531
|
+
if (!rect)
|
|
532
|
+
return;
|
|
533
|
+
const { style } = (0, core_1.placeFloating)({
|
|
534
|
+
rect,
|
|
535
|
+
gap: 4,
|
|
536
|
+
flipBelow: 280,
|
|
537
|
+
anchor: importExportTriggerRef.current,
|
|
538
|
+
});
|
|
539
|
+
setImportExportPos(style);
|
|
540
|
+
};
|
|
541
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: reposition each time it opens
|
|
542
|
+
React.useLayoutEffect(() => {
|
|
543
|
+
if (openMenu === "importexport")
|
|
544
|
+
placeImportExportMenu();
|
|
545
|
+
}, [openMenu]);
|
|
438
546
|
// close any open menu on outside click (anything not inside a menu or its
|
|
439
547
|
// trigger) or Escape
|
|
440
548
|
React.useEffect(() => {
|
|
@@ -585,6 +693,13 @@ function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: fi
|
|
|
585
693
|
close: () => setOpenMenu(null),
|
|
586
694
|
contentRef: importExportMenuRef,
|
|
587
695
|
});
|
|
696
|
+
// crisp/#807: registers the (now-portaled) Import/Export menu on the
|
|
697
|
+
// shared floating-layer stack, the same reason `Menu` itself does.
|
|
698
|
+
React.useEffect(() => {
|
|
699
|
+
if (openMenu !== "importexport" || !importExportMenuRef.current)
|
|
700
|
+
return;
|
|
701
|
+
return (0, core_1.registerFloatingLayer)(importExportMenuRef.current);
|
|
702
|
+
}, [openMenu]);
|
|
588
703
|
// #754: generalized from the Filter-only `filterFieldPicker` (#592) to
|
|
589
704
|
// also drive Sort's own field picker and View settings' add-attribute
|
|
590
705
|
// screen — all three offer the identical nested-drill-down construct on
|
|
@@ -641,16 +756,23 @@ function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: fi
|
|
|
641
756
|
// worse than an imperfect word order); `crispMessages` rather than a
|
|
642
757
|
// second `useCrispMessage` call, since this only fires on the branch that
|
|
643
758
|
// needs it.
|
|
759
|
+
// crisp/#788: "Sorted by" and the field name are NOT a font-weight split
|
|
760
|
+
// (both measure 500/medium live) -- the difference is colour/opacity only:
|
|
761
|
+
// "Sorted by" at 63% black, the field name at full-strength near-black
|
|
762
|
+
// (rgb(16,17,18)). The "+N" suffix is smaller (12px vs 14px) and its own
|
|
763
|
+
// mid-grey (rgb(80,81,85)), not muted-63%-black either -- three distinct
|
|
764
|
+
// treatments, not two. `sortField` isolates the resolved label so the
|
|
765
|
+
// default (non-`sortTriggerLabel`) render can wrap each part in its own
|
|
766
|
+
// span; `sortedLabel` stays a single string for the `sortTriggerLabel`
|
|
767
|
+
// escape hatch (a caller-supplied formatter can't be split, by definition)
|
|
768
|
+
// and the empty-state `sortLabel`.
|
|
769
|
+
const sortField = resolveColumnPath(sortColumns, sorts[0]?.key ?? "").at(-1)?.label;
|
|
644
770
|
const sortedLabel = sortTriggerLabel
|
|
645
771
|
? sortTriggerLabel(sorts, sortColumns)
|
|
646
772
|
: sorts.length
|
|
647
|
-
? `${crispMessages["Sorted by"] ?? "Sorted by"} ${
|
|
648
|
-
// #754: sorts[0].key may be a dot-joined nested path
|
|
649
|
-
// ("team.jobTitle") — resolve it the same way the chip and sort
|
|
650
|
-
// row do, rather than a flat find that fails on a nested key.
|
|
651
|
-
resolveColumnPath(sortColumns, sorts[0].key).at(-1)?.label}${sorts.length > 1 ? ` +${sorts.length - 1}` : ""}`
|
|
773
|
+
? `${crispMessages["Sorted by"] ?? "Sorted by"} ${sortField}${sorts.length > 1 ? ` +${sorts.length - 1}` : ""}`
|
|
652
774
|
: sortLabel;
|
|
653
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: (0, tabletoolbar_recipe_1.tabletoolbarRecipe)({ className }), ...rest, children: (0, jsx_runtime_1.jsxs)("div", { className: "crisp-tabletoolbar-toolbar", "data-inline": inline ? "" : undefined, children: [showSort && ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-toolgroup", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: `crisp-tabletoolbar-tool${sorts.length ? " crisp-tabletoolbar-tool--active" : ""}`, onClick: () => setOpenMenu(openMenu === "sort" ? null : "sort"), "aria-haspopup": "dialog", "aria-expanded": openMenu === "sort", "data-menu-trigger": true, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowUpDown, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" }), sortedLabel] }), openMenu === "sort" && ((0, jsx_runtime_1.jsxs)("div", { ref: sortListRef, className: "crisp-tabletoolbar-menu crisp-tabletoolbar-sortpop", role: "dialog", "aria-label": sortLabel, children: [sorts.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "crisp-tabletoolbar-sort-empty", children: noSortsLabel })) : (sorts.map((s, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-tabletoolbar-sort-row", onDragOver: (e) => {
|
|
775
|
+
return ((0, jsx_runtime_1.jsx)("div", { ref: rootRef, className: (0, tabletoolbar_recipe_1.tabletoolbarRecipe)({ className }), ...rest, children: (0, jsx_runtime_1.jsxs)("div", { className: "crisp-tabletoolbar-toolbar", "data-inline": inline ? "" : undefined, children: [showSort && ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-toolgroup", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: `crisp-tabletoolbar-tool${sorts.length ? " crisp-tabletoolbar-tool--active" : " crisp-tabletoolbar-tool--dashed"}`, onClick: () => setOpenMenu(openMenu === "sort" ? null : "sort"), "aria-haspopup": "dialog", "aria-expanded": openMenu === "sort", "data-menu-trigger": true, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowUpDown, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" }), sortTriggerLabel || !sorts.length ? (sortedLabel) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-sorted-prefix", children: crispMessages["Sorted by"] ?? "Sorted by" }), " ", (0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-sorted-field", children: sortField }), sorts.length > 1 && ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-sorted-count", children: [" ", "+", sorts.length - 1] }))] }))] }), openMenu === "sort" && ((0, jsx_runtime_1.jsxs)("div", { ref: sortListRef, className: "crisp-tabletoolbar-menu crisp-tabletoolbar-sortpop", role: "dialog", "aria-label": sortLabel, children: [sorts.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "crisp-tabletoolbar-sort-empty", children: noSortsLabel })) : (sorts.map((s, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-tabletoolbar-sort-row", onDragOver: (e) => {
|
|
654
776
|
if (dragSort !== null)
|
|
655
777
|
e.preventDefault();
|
|
656
778
|
}, onDrop: () => {
|
|
@@ -687,7 +809,7 @@ function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: fi
|
|
|
687
809
|
label: ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-sort-optlabel", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowDownWideNarrow, { size: 15, strokeWidth: 1.75 }), descendingLabel] })),
|
|
688
810
|
keywords: descendingLabel,
|
|
689
811
|
},
|
|
690
|
-
], "aria-label": sortDirectionLabel }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-tabletoolbar-sort-remove", onClick: () => removeSort(i), "aria-label": removeSortLabel, children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: 15, strokeWidth: 1.75 }) })] }, s.key)))), (0, jsx_runtime_1.jsx)("div", { className: "crisp-tabletoolbar-sort-addrow", children: (0, jsx_runtime_1.jsxs)("button", { ref: addSortRef, type: "button", className: "crisp-tabletoolbar-sort-add", onClick: addSort, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 15, strokeWidth: 1.75 }), addSortLabel] }) }), helpHref && ((0, jsx_runtime_1.jsx)("div", { className: "crisp-tabletoolbar-sort-foot", children: (0, jsx_runtime_1.jsxs)("a", { className: "crisp-tabletoolbar-sort-learn", href: helpHref, target: "_blank", rel: "noreferrer", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CircleHelp, { size: 14, strokeWidth: 1.75 }), learnSortingLabel] }) }))] }))] })), showSort && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-divider", "aria-hidden": "true" })), (0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-toolgroup", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: `crisp-tabletoolbar-tool
|
|
812
|
+
], "aria-label": sortDirectionLabel }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-tabletoolbar-sort-remove", onClick: () => removeSort(i), "aria-label": removeSortLabel, children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: 15, strokeWidth: 1.75 }) })] }, s.key)))), (0, jsx_runtime_1.jsx)("div", { className: "crisp-tabletoolbar-sort-addrow", children: (0, jsx_runtime_1.jsxs)("button", { ref: addSortRef, type: "button", className: "crisp-tabletoolbar-sort-add", onClick: addSort, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 15, strokeWidth: 1.75 }), addSortLabel] }) }), helpHref && ((0, jsx_runtime_1.jsx)("div", { className: "crisp-tabletoolbar-sort-foot", children: (0, jsx_runtime_1.jsxs)("a", { className: "crisp-tabletoolbar-sort-learn", href: helpHref, target: "_blank", rel: "noreferrer", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CircleHelp, { size: 14, strokeWidth: 1.75 }), learnSortingLabel] }) }))] }))] })), showSort && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-divider", "aria-hidden": "true" })), (0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-toolgroup", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: `crisp-tabletoolbar-tool${activeFilters ? " crisp-tabletoolbar-tool--active" : " crisp-tabletoolbar-tool--dashed"}`, onClick: () => {
|
|
691
813
|
setFieldPickerPath([]);
|
|
692
814
|
setOpenMenu(openMenu === "filter" ? null : "filter");
|
|
693
815
|
}, "aria-haspopup": "dialog", "aria-expanded": openMenu === "filter", "data-menu-trigger": true, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ListFilter, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" }), filterTriggerLabel
|
|
@@ -786,43 +908,54 @@ function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: fi
|
|
|
786
908
|
}, children: label }, label))) })] })) : ((0, jsx_runtime_1.jsx)("input", { className: "crisp-tabletoolbar-menu-input", type: col?.type === "number" ? "number" : "text", placeholder: filterValuePlaceholder, "aria-label": `${col?.label} filter value`,
|
|
787
909
|
// biome-ignore lint/a11y/noAutofocus: focus the value field
|
|
788
910
|
autoFocus: true, value: cond.value, onChange: (e) => patchFilter(cond.id, { value: e.target.value }) })) }))] }, cond.id));
|
|
789
|
-
}), showViewSettings && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-divider", "aria-hidden": "true" })), showViewSettings && ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-toolgroup", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-tabletoolbar-tool crisp-tabletoolbar-tool--
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
},
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
}, children: [
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
911
|
+
}), showViewSettings && !viewSettingsTarget && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-divider", "aria-hidden": "true" })), showViewSettings && ((0, jsx_runtime_1.jsx)(ViewBarSlot, { target: viewSettingsTarget, children: (0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-toolgroup", children: [(0, jsx_runtime_1.jsxs)("button", { ref: viewSettingsTriggerRef, type: "button", className: "crisp-tabletoolbar-tool crisp-tabletoolbar-tool--raised", onClick: () => {
|
|
912
|
+
if (openMenu === "viewsettings") {
|
|
913
|
+
setOpenMenu(null);
|
|
914
|
+
}
|
|
915
|
+
else {
|
|
916
|
+
setAddingAttribute(false);
|
|
917
|
+
setFieldPickerPath([]);
|
|
918
|
+
setFilterQuery("");
|
|
919
|
+
setOpenMenu("viewsettings");
|
|
920
|
+
}
|
|
921
|
+
}, "aria-haspopup": "dialog", "aria-expanded": openMenu === "viewsettings", "data-menu-trigger": true, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.SlidersHorizontal, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" }), viewSettingsLabel, (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" })] }), openMenu === "viewsettings" && ((0, jsx_runtime_1.jsx)(core_1.FloatingPortal, { sourceRef: rootRef, children: (0, jsx_runtime_1.jsx)("span", { className: (0, tabletoolbar_recipe_1.tabletoolbarRecipe)(), children: addingAttribute ? ((0, jsx_runtime_1.jsx)("div", { ref: viewSettingsContentRef, className: "crisp-tabletoolbar-menu", role: "dialog", "aria-label": addAttributeToViewLabel, style: {
|
|
922
|
+
position: "fixed",
|
|
923
|
+
zIndex: 70,
|
|
924
|
+
...viewSettingsPos,
|
|
925
|
+
}, children: nestedFieldPicker(hiddenAttrs, showAttr, searchAttributesPlaceholder, searchAttributesPlaceholder) })) : ((0, jsx_runtime_1.jsxs)("div", { ref: viewSettingsContentRef, className: "crisp-tabletoolbar-menu crisp-tabletoolbar-sortpop", role: "dialog", "aria-label": viewSettingsLabel, style: {
|
|
926
|
+
position: "fixed",
|
|
927
|
+
zIndex: 70,
|
|
928
|
+
...viewSettingsPos,
|
|
929
|
+
}, children: [shownAttrs.map((col, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-tabletoolbar-sort-row", onDragOver: (e) => {
|
|
930
|
+
if (dragAttr !== null)
|
|
931
|
+
e.preventDefault();
|
|
932
|
+
}, onDrop: () => {
|
|
933
|
+
if (dragAttr !== null)
|
|
934
|
+
moveAttr(dragAttr, i);
|
|
935
|
+
setDragAttr(null);
|
|
936
|
+
}, children: [(0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-tabletoolbar-sort-grip", "aria-label": reorderAttributeLabel, draggable: true, onDragStart: () => setDragAttr(i), onDragEnd: () => setDragAttr(null), children: (0, jsx_runtime_1.jsx)(lucide_react_1.GripVertical, { size: 15, strokeWidth: 1.75 }) }), (0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-sort-optlabel crisp-tabletoolbar-sort-field", children: [col.icon ? ((0, jsx_runtime_1.jsx)(col.icon, { size: 15, strokeWidth: 1.75 })) : null, col.label] }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-tabletoolbar-sort-remove", onClick: () => hideAttr(col.key), "aria-label": hideAttributeLabel?.(col.label) ??
|
|
937
|
+
`${crispMessages.Hide ?? "Hide"} ${col.label} ${crispMessages["from view"] ?? "from view"}`, children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: 15, strokeWidth: 1.75 }) })] }, col.key))), (0, jsx_runtime_1.jsx)("div", { className: "crisp-tabletoolbar-sort-addrow", children: (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-tabletoolbar-sort-add", onClick: () => {
|
|
938
|
+
setAddingAttribute(true);
|
|
939
|
+
setFieldPickerPath([]);
|
|
940
|
+
setFilterQuery("");
|
|
941
|
+
}, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 15, strokeWidth: 1.75 }), addAttributeToViewLabel] }) })] })) }) }))] }) })), (onImportCsv ||
|
|
813
942
|
onExportCsv ||
|
|
814
943
|
onExportExcel ||
|
|
815
|
-
importExportHelpHref) && ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-toolgroup", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-tabletoolbar-tool crisp-tabletoolbar-tool--raised", onClick: () => setOpenMenu(openMenu === "importexport" ? null : "importexport"), "aria-haspopup": "menu", "aria-expanded": openMenu === "importexport", "data-menu-trigger": true, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Upload, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" }), importExportLabel, (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" })] }), openMenu === "importexport" && ((0, jsx_runtime_1.
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
944
|
+
importExportHelpHref) && ((0, jsx_runtime_1.jsx)(ViewBarSlot, { target: importExportTarget, children: (0, jsx_runtime_1.jsxs)("span", { className: "crisp-tabletoolbar-toolgroup", children: [(0, jsx_runtime_1.jsxs)("button", { ref: importExportTriggerRef, type: "button", className: "crisp-tabletoolbar-tool crisp-tabletoolbar-tool--raised", onClick: () => setOpenMenu(openMenu === "importexport" ? null : "importexport"), "aria-haspopup": "menu", "aria-expanded": openMenu === "importexport", "data-menu-trigger": true, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Upload, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" }), importExportLabel, (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" })] }), openMenu === "importexport" && ((0, jsx_runtime_1.jsx)(core_1.FloatingPortal, { sourceRef: rootRef, children: (0, jsx_runtime_1.jsx)("span", { className: (0, tabletoolbar_recipe_1.tabletoolbarRecipe)(), children: (0, jsx_runtime_1.jsxs)("div", { ref: importExportMenuRef, className: "crisp-tabletoolbar-menu", role: "menu", "aria-label": importExportLabel, onKeyDown: onImportExportKeyDown, style: {
|
|
945
|
+
position: "fixed",
|
|
946
|
+
zIndex: 70,
|
|
947
|
+
...importExportPos,
|
|
948
|
+
}, children: [onImportCsv && ((0, jsx_runtime_1.jsxs)("button", { type: "button", role: "menuitem", className: "crisp-tabletoolbar-menu-item", onClick: () => {
|
|
949
|
+
onImportCsv();
|
|
950
|
+
setOpenMenu(null);
|
|
951
|
+
}, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Upload, { size: 15, strokeWidth: 1.75 }), importCsvLabel] })), onImportCsv && (onExportCsv || onExportExcel) && ((0, jsx_runtime_1.jsx)("hr", { className: "crisp-tabletoolbar-menu-sep" })), onExportCsv && ((0, jsx_runtime_1.jsxs)("button", { type: "button", role: "menuitem", className: "crisp-tabletoolbar-menu-item", onClick: () => {
|
|
952
|
+
onExportCsv();
|
|
953
|
+
setOpenMenu(null);
|
|
954
|
+
}, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Download, { size: 15, strokeWidth: 1.75 }), exportCsvLabel] })), onExportExcel && ((0, jsx_runtime_1.jsxs)("button", { type: "button", role: "menuitem", className: "crisp-tabletoolbar-menu-item", onClick: () => {
|
|
955
|
+
onExportExcel();
|
|
956
|
+
setOpenMenu(null);
|
|
957
|
+
}, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Download, { size: 15, strokeWidth: 1.75 }), exportExcelLabel] })), importExportHelpHref &&
|
|
958
|
+
(onImportCsv || onExportCsv || onExportExcel) && ((0, jsx_runtime_1.jsx)("hr", { className: "crisp-tabletoolbar-menu-sep" })), importExportHelpHref && ((0, jsx_runtime_1.jsxs)("a", { className: "crisp-tabletoolbar-menu-item", role: "menuitem", href: importExportHelpHref, target: "_blank", rel: "noreferrer", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CircleHelp, { size: 15, strokeWidth: 1.75 }), learnImportExportLabel] }))] }) }) }))] }) })), (0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-spacer" }), count != null && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-tabletoolbar-count", children: count })), children] }) }));
|
|
826
959
|
}
|
|
827
960
|
/**
|
|
828
961
|
* The Sort/Filter chip's own chrome (`.crisp-tabletoolbar-tool`), standalone
|
|
@@ -74,14 +74,21 @@ const filterChipChrome = `
|
|
|
74
74
|
& .crisp-tabletoolbar-datepop-presets { display: flex; flex-wrap: wrap; gap: ${tokens_1.contract.space["1"]}; margin-top: ${tokens_1.contract.space["2"]}; padding: 0 ${tokens_1.contract.space["1"]}; }
|
|
75
75
|
& .crisp-tabletoolbar-datepop-preset { height: ${tokens_1.contract.size.chip}; padding: 0 ${tokens_1.contract.space["2"]}; border: none; border-radius: ${tokens_1.contract.radius.chip}; background: ${tokens_1.contract.bgRaised}; color: ${tokens_1.contract.fgPrimary}; font-family: inherit; font-size: ${tokens_1.contract.text.sm}; cursor: pointer; }
|
|
76
76
|
& .crisp-tabletoolbar-datepop-preset:hover { background: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 8%, transparent); }`;
|
|
77
|
-
// #595
|
|
78
|
-
// view bar: `28px` tall, `radius.md`
|
|
79
|
-
// (`rgb(
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
//
|
|
77
|
+
// #595, corrected #772 (re-measured live 2026-09-25): the view bar's raised
|
|
78
|
+
// trigger chrome — `app.attio.com`'s own view bar: `28px` tall, `radius.md`
|
|
79
|
+
// (8px), background `bgSurface` (white, `rgb(255,255,255)` exact match — the
|
|
80
|
+
// #595 pass originally measured `bgSurfaceMuted`/`rgb(246,247,247)`, which
|
|
81
|
+
// re-measuring live this pass shows was wrong, not a later Attio change: ALL
|
|
82
|
+
// THREE of the switcher, View settings and Import/Export read pure white)
|
|
83
|
+
// and `elevation.field`'s exact 3-layer shadow (`inset 0 0 0 1px transparent,
|
|
84
|
+
// 0 0 2px rgba(28,40,64,.18), 0 1px 3px rgba(0,0,0,.04)`) — distinct from
|
|
85
|
+
// Sort/Filter's plain ringed `.tool` (no elevation shadow; see `--dashed` in
|
|
86
|
+
// `tabletoolbar.chrome.ts` for their own OWN empty-state chrome). Originally
|
|
87
|
+
// built for Import/Export alone ("the only trigger... with a trailing
|
|
88
|
+
// chevron") — that was also wrong: View settings and the view switcher both
|
|
89
|
+
// carry one too, confirmed live (3 children each: icon, label, chevron).
|
|
90
|
+
// Now shared by View settings' own trigger (`tabletoolbar.tsx`) as well as
|
|
91
|
+
// Import/Export's. Overrides `.tool`'s own base background/shadow by cascade
|
|
85
92
|
// order (this block is appended after `toolbarChromeBody`, which defines
|
|
86
93
|
// them), the same way `.tool--ghost` already does. `border`/`font-family`/
|
|
87
94
|
// `cursor` are repeated here too, even though `.tool`'s own base rule (in
|
|
@@ -91,7 +98,18 @@ const filterChipChrome = `
|
|
|
91
98
|
// behind `chrome.ts`'s function call is invisible to it; harmless repeats,
|
|
92
99
|
// not a real gap.
|
|
93
100
|
const importExportChrome = `
|
|
94
|
-
& .crisp-tabletoolbar-tool--raised { border: none; background: ${tokens_1.contract.
|
|
101
|
+
& .crisp-tabletoolbar-tool--raised { border: none; background: ${tokens_1.contract.bgSurface}; box-shadow: ${tokens_1.elevation.field}; font-family: inherit; cursor: pointer; }`;
|
|
102
|
+
// crisp/#788: the Sort trigger's own "Sorted by X (+N)" label, measured live
|
|
103
|
+
// against Attio's own chip -- three parts, not one flat string, and NOT a
|
|
104
|
+
// font-weight split (all three read 500/medium): "Sorted by" is muted (63%
|
|
105
|
+
// black), the resolved field name is full-strength near-black, and a
|
|
106
|
+
// trailing "+N" (when more than one sort is active) is both smaller (12px
|
|
107
|
+
// vs 14px) and its own mid-grey, distinct from the "Sorted by" muted tone.
|
|
108
|
+
// TableToolbar-only, same reasoning as `filterChipChrome` above (RecordsTable
|
|
109
|
+
// keeps its own older Sort label markup, not touched here).
|
|
110
|
+
const sortedLabelChrome = `
|
|
111
|
+
& .crisp-tabletoolbar-sorted-prefix { color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 63%, transparent); }
|
|
112
|
+
& .crisp-tabletoolbar-sorted-count { font-size: ${tokens_1.contract.text.sm}; color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 73%, transparent); }`;
|
|
95
113
|
// The table toolbar, measured: 28px controls, the Sort/Filter buttons and
|
|
96
114
|
// the menus they open, sort-condition rows, and the filter chips. The chrome
|
|
97
115
|
// itself lives in ./tabletoolbar.chrome.ts because RecordsTable renders the
|
|
@@ -110,6 +128,7 @@ ${(0, tabletoolbar_chrome_1.toolbarChromeHead)("tabletoolbar")}
|
|
|
110
128
|
${(0, tabletoolbar_chrome_1.toolbarChromeBody)("tabletoolbar")}
|
|
111
129
|
${filterChipChrome}
|
|
112
130
|
${importExportChrome}
|
|
131
|
+
${sortedLabelChrome}
|
|
113
132
|
${core_1.rtlFlipCss}
|
|
114
133
|
`,
|
|
115
134
|
});
|
package/dist/cjs/index.js
CHANGED
|
@@ -102,7 +102,6 @@ __exportStar(require("./product/objectsettings"), exports);
|
|
|
102
102
|
__exportStar(require("./product/onboarding"), exports);
|
|
103
103
|
__exportStar(require("./product/recordpage"), exports);
|
|
104
104
|
__exportStar(require("./product/recordpanel"), exports);
|
|
105
|
-
__exportStar(require("./product/recordstable"), exports);
|
|
106
105
|
__exportStar(require("./product/richtext"), exports);
|
|
107
106
|
__exportStar(require("./product/savedviews"), exports);
|
|
108
107
|
__exportStar(require("./product/settingssection"), exports);
|
|
@@ -110,7 +109,6 @@ __exportStar(require("./product/settingsshell"), exports);
|
|
|
110
109
|
__exportStar(require("./product/sidebar"), exports);
|
|
111
110
|
__exportStar(require("./product/statlist"), exports);
|
|
112
111
|
__exportStar(require("./product/tasklist"), exports);
|
|
113
|
-
__exportStar(require("./product/taskstable"), exports);
|
|
114
112
|
__exportStar(require("./product/themepicker"), exports);
|
|
115
113
|
__exportStar(require("./product/trialbanner"), exports);
|
|
116
114
|
__exportStar(require("./product/viewtoggle"), exports);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tagTone = tagTone;
|
|
4
|
+
// deterministic pastel colour per tag value (a select option keeps its colour)
|
|
5
|
+
const TAG_TONES = [
|
|
6
|
+
"brand",
|
|
7
|
+
"success",
|
|
8
|
+
"warning",
|
|
9
|
+
"danger",
|
|
10
|
+
"purple",
|
|
11
|
+
"cyan",
|
|
12
|
+
"orange",
|
|
13
|
+
];
|
|
14
|
+
function tagTone(t) {
|
|
15
|
+
let h = 0;
|
|
16
|
+
for (let i = 0; i < t.length; i++)
|
|
17
|
+
h = (h * 31 + t.charCodeAt(i)) >>> 0;
|
|
18
|
+
return TAG_TONES[h % TAG_TONES.length];
|
|
19
|
+
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.recordpageRecipe = exports.recordPageLabels = exports.RecordPage = exports.RecordDetails = void 0;
|
|
3
|
+
exports.recordpageRecipe = exports.recordPageLabels = exports.RecordPage = exports.RecordDetails = exports.useEditableField = exports.editableInputType = exports.tagTone = void 0;
|
|
4
|
+
var column_1 = require("./column");
|
|
5
|
+
Object.defineProperty(exports, "tagTone", { enumerable: true, get: function () { return column_1.tagTone; } });
|
|
6
|
+
var editable_field_1 = require("./editable-field");
|
|
7
|
+
Object.defineProperty(exports, "editableInputType", { enumerable: true, get: function () { return editable_field_1.editableInputType; } });
|
|
8
|
+
Object.defineProperty(exports, "useEditableField", { enumerable: true, get: function () { return editable_field_1.useEditableField; } });
|
|
4
9
|
var recordpage_1 = require("./recordpage");
|
|
5
10
|
Object.defineProperty(exports, "RecordDetails", { enumerable: true, get: function () { return recordpage_1.RecordDetails; } });
|
|
6
11
|
Object.defineProperty(exports, "RecordPage", { enumerable: true, get: function () { return recordpage_1.RecordPage; } });
|
|
@@ -47,8 +47,23 @@ const spinner_1 = require("../../components/spinner");
|
|
|
47
47
|
const switch_1 = require("../../components/switch");
|
|
48
48
|
const tabs_1 = require("../../components/tabs");
|
|
49
49
|
const core_1 = require("../../core");
|
|
50
|
-
const
|
|
50
|
+
const column_1 = require("./column");
|
|
51
|
+
const editable_field_1 = require("./editable-field");
|
|
51
52
|
const recordpage_recipe_1 = require("./recordpage.recipe");
|
|
53
|
+
// crisp/#798: the details column's own drag clamp -- re-measured live on
|
|
54
|
+
// Attio's own record page (a real drag test, not a source read): min 619px,
|
|
55
|
+
// max 1170px, default (also the double-click-reset target) 734px. These
|
|
56
|
+
// replace an earlier, much narrower 300/560/320 that was never actually
|
|
57
|
+
// checked against Attio and turned out roughly half the real max. Confirmed
|
|
58
|
+
// live these are literal px, not a viewport ratio: at a narrower emulated
|
|
59
|
+
// width the already-dragged-to-max column shrank below 1170px, but its OWN
|
|
60
|
+
// `getComputedStyle(...).width` still read a plain px number the whole
|
|
61
|
+
// time (not a `%`) — that shrink is ordinary flex-shrink (both panels
|
|
62
|
+
// share `flex: 1 1 auto` and can't both keep their preferred width once the
|
|
63
|
+
// window is too narrow), not the clamp itself changing with viewport width.
|
|
64
|
+
const DETAILS_MIN_W = 619;
|
|
65
|
+
const DETAILS_MAX_W = 1170;
|
|
66
|
+
const DETAILS_DEFAULT_W = 734;
|
|
52
67
|
function valueEmpty(v) {
|
|
53
68
|
return v == null || v === "" || (Array.isArray(v) && v.length === 0);
|
|
54
69
|
}
|
|
@@ -212,7 +227,7 @@ function TagsValue({ values }) {
|
|
|
212
227
|
const [expanded, setExpanded] = React.useState(false);
|
|
213
228
|
const overflow = values.length - 1;
|
|
214
229
|
const shown = expanded ? values : values.slice(0, 1);
|
|
215
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [shown.map((t) => ((0, jsx_runtime_1.jsx)("span", { className: "crisp-recordstable-tag", "data-tone": (0,
|
|
230
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [shown.map((t) => ((0, jsx_runtime_1.jsx)("span", { className: "crisp-recordstable-tag", "data-tone": (0, column_1.tagTone)(t), children: t }, t))), !expanded && overflow > 0 && ((0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-recordpage-morevalues", onClick: () => setExpanded(true), children: ["+", overflow] }))] }));
|
|
216
231
|
}
|
|
217
232
|
function FieldValue({ col, row, labels, }) {
|
|
218
233
|
const v = row[col.key];
|
|
@@ -316,7 +331,7 @@ function EmptyCard({ icon, children, }) {
|
|
|
316
331
|
*/
|
|
317
332
|
function RecordDetails({ record, columns, sections, onEdit, labels, className, ...rest }) {
|
|
318
333
|
const t = useRecordPageLabels(labels);
|
|
319
|
-
const { editingKey, pendingKey, error, openEditing, closeEditing, commit } = (0,
|
|
334
|
+
const { editingKey, pendingKey, error, openEditing, closeEditing, commit } = (0, editable_field_1.useEditableField)(onEdit);
|
|
320
335
|
const [detailsOpen, setDetailsOpen] = React.useState(true);
|
|
321
336
|
const [searchOpen, setSearchOpen] = React.useState(false);
|
|
322
337
|
const [fieldQuery, setFieldQuery] = React.useState("");
|
|
@@ -406,7 +421,7 @@ function RecordDetails({ record, columns, sections, onEdit, labels, className, .
|
|
|
406
421
|
}
|
|
407
422
|
if (canEdit && editingKey === col.key) {
|
|
408
423
|
const value = record[col.key];
|
|
409
|
-
const editor = (0,
|
|
424
|
+
const editor = (0, editable_field_1.editableInputType)(col.type);
|
|
410
425
|
return ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-field", children: [label, (0, jsx_runtime_1.jsxs)("span", { className: "crisp-recordpage-field-value", children: [(0, jsx_runtime_1.jsx)("input", { className: "crisp-recordpage-edit",
|
|
411
426
|
// biome-ignore lint/a11y/noAutofocus: focus the field the moment it opens
|
|
412
427
|
autoFocus: true, ...editor, disabled: isPending, defaultValue: value == null ? "" : String(value), "aria-label": `Edit ${col.label}`, onKeyDown: (e) => {
|
|
@@ -456,7 +471,7 @@ function RecordPage({ record, columns, collection = "Records", labels, onBack, o
|
|
|
456
471
|
const tasks = tasksProp ?? internalTasks;
|
|
457
472
|
const [showAllActivity, setShowAllActivity] = React.useState(false);
|
|
458
473
|
// Drag-resizable left details column.
|
|
459
|
-
const [detailsW, setDetailsW] = React.useState(
|
|
474
|
+
const [detailsW, setDetailsW] = React.useState(DETAILS_DEFAULT_W);
|
|
460
475
|
const [resizing, setResizing] = React.useState(false);
|
|
461
476
|
const dragRef = React.useRef(null);
|
|
462
477
|
const onResizeDown = (e) => {
|
|
@@ -474,7 +489,7 @@ function RecordPage({ record, columns, collection = "Records", labels, onBack, o
|
|
|
474
489
|
if (!dragRef.current)
|
|
475
490
|
return;
|
|
476
491
|
const next = dragRef.current.w + dragRef.current.dir * (e.clientX - dragRef.current.x);
|
|
477
|
-
setDetailsW(Math.max(
|
|
492
|
+
setDetailsW(Math.max(DETAILS_MIN_W, Math.min(DETAILS_MAX_W, next)));
|
|
478
493
|
};
|
|
479
494
|
const onResizeUp = (e) => {
|
|
480
495
|
dragRef.current = null;
|
|
@@ -659,7 +674,7 @@ function RecordPage({ record, columns, collection = "Records", labels, onBack, o
|
|
|
659
674
|
const effectivePanel = tabsProp
|
|
660
675
|
? (active) => tabsProp.find((tb) => tb.id === active)?.render()
|
|
661
676
|
: builtinPanel;
|
|
662
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, recordpage_recipe_1.recordpageRecipe)({ className }), ...rest, children: [(0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-topbar", children: [(0, jsx_runtime_1.jsxs)("nav", { className: "crisp-recordpage-crumbs", "aria-label": t.breadcrumb, children: [(0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-crumb", onClick: onBack, "aria-label": `Back to ${collection}`, children: collection }), (0, jsx_runtime_1.jsx)("span", { className: "crisp-recordpage-crumb-sep", children: "/" }), (0, jsx_runtime_1.jsx)("span", { className: "crisp-recordpage-crumb-name", children: name })] }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-actions", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-recordpage-action crisp-recordpage-action--ghost", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Sparkles, { size: 14, strokeWidth: 1.75, color: "var(--crisp-bg-brand-solid)" }), t.askAttio] }), onToggleFull && ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-action crisp-recordpage-action--icon", onClick: onToggleFull, "aria-label": full ? t.exitFullScreen : t.fullScreen, children: full ? ((0, jsx_runtime_1.jsx)(lucide_react_1.Minimize2, { size: 15, strokeWidth: 1.75 })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.Maximize2, { size: 15, strokeWidth: 1.75 })) })), (0, jsx_runtime_1.jsxs)(menu_1.Menu, { align: "end", "aria-label": t.recordActions, trigger: (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-action crisp-recordpage-action--icon", "aria-label": t.recordActions, children: (0, jsx_runtime_1.jsx)(lucide_react_1.MoreHorizontal, { size: 16, strokeWidth: 1.75 }) }), children: [(0, jsx_runtime_1.jsx)(menu_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { size: 15, strokeWidth: 1.75 }), shortcut: "\u2318C", children: t.copyRecordLink }), (0, jsx_runtime_1.jsx)(menu_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 15, strokeWidth: 1.75 }), children: t.addToList }), (0, jsx_runtime_1.jsx)(menu_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Star, { size: 15, strokeWidth: 1.75 }), onSelect: () => setFavorite((f) => !f), children: favorite ? t.removeFromFavourites : t.addToFavourites }), (0, jsx_runtime_1.jsx)(menu_1.MenuSeparator, {}), (0, jsx_runtime_1.jsx)(menu_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Trash2, { size: 15, strokeWidth: 1.75 }), danger: true, shortcut: "\u232B", children: t.deleteRecord })] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-body", children: [(0, jsx_runtime_1.jsxs)("aside", { className: "crisp-recordpage-details", style: { width: detailsW }, children: [(0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-entity", children: [entity?.avatar ? ((0, jsx_runtime_1.jsx)("img", { className: "crisp-recordpage-entity-logo", src: entity.avatar, alt: "" })) : ((0, jsx_runtime_1.jsx)(avatar_1.Avatar, { size: "lg", shape: "rounded", tone: "brand", children: name.charAt(0) })), (0, jsx_runtime_1.jsx)("span", { className: "crisp-recordpage-entity-name", children: name }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-entity-iconbtn", "aria-label": t.editRecord, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Pencil, { size: 15, strokeWidth: 1.75 }) }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-entity-iconbtn", "data-active": favorite ? "" : undefined, "aria-pressed": favorite, onClick: () => setFavorite((f) => !f), "aria-label": favorite ? t.removeFromFavourites : t.addToFavourites, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Star, { size: 15, strokeWidth: 1.75 }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-quickactions", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-recordpage-compose", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Mail, { size: 16, strokeWidth: 1.75 }), t.composeEmail] }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-quickbtn", "aria-label": t.copyRecordLink, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { size: 15, strokeWidth: 1.75 }) }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-quickbtn", "aria-label": t.logANote, children: (0, jsx_runtime_1.jsx)(lucide_react_1.FileText, { size: 15, strokeWidth: 1.75 }) }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-quickbtn", "aria-label": t.linkRecords, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Share2, { size: 15, strokeWidth: 1.75 }) }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-quickbtn", "aria-label": t.createATask, children: (0, jsx_runtime_1.jsx)(lucide_react_1.SquareCheck, { size: 15, strokeWidth: 1.75 }) })] }), (0, jsx_runtime_1.jsx)(RecordDetails, { record: record, columns: columns, sections: sections, onEdit: onEdit, labels: labels }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-section", children: [(0, jsx_runtime_1.jsx)(SectionHead, { title: t.tabs.lists, action: (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-recordpage-addbtn", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 14, strokeWidth: 2 }), t.addToList] }) }), (0, jsx_runtime_1.jsx)("div", { className: "crisp-recordpage-emptystate", children: t.noLists })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "crisp-recordpage-resizer", "data-active": resizing ? "" : undefined, role: "separator", "aria-orientation": "vertical", "aria-label": t.resizeDetails, "aria-valuenow": Math.round(detailsW), "aria-valuemin":
|
|
677
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, recordpage_recipe_1.recordpageRecipe)({ className }), ...rest, children: [(0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-topbar", children: [(0, jsx_runtime_1.jsxs)("nav", { className: "crisp-recordpage-crumbs", "aria-label": t.breadcrumb, children: [(0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-crumb", onClick: onBack, "aria-label": `Back to ${collection}`, children: collection }), (0, jsx_runtime_1.jsx)("span", { className: "crisp-recordpage-crumb-sep", children: "/" }), (0, jsx_runtime_1.jsx)("span", { className: "crisp-recordpage-crumb-name", children: name })] }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-actions", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-recordpage-action crisp-recordpage-action--ghost", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Sparkles, { size: 14, strokeWidth: 1.75, color: "var(--crisp-bg-brand-solid)" }), t.askAttio] }), onToggleFull && ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-action crisp-recordpage-action--icon", onClick: onToggleFull, "aria-label": full ? t.exitFullScreen : t.fullScreen, children: full ? ((0, jsx_runtime_1.jsx)(lucide_react_1.Minimize2, { size: 15, strokeWidth: 1.75 })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.Maximize2, { size: 15, strokeWidth: 1.75 })) })), (0, jsx_runtime_1.jsxs)(menu_1.Menu, { align: "end", "aria-label": t.recordActions, trigger: (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-action crisp-recordpage-action--icon", "aria-label": t.recordActions, children: (0, jsx_runtime_1.jsx)(lucide_react_1.MoreHorizontal, { size: 16, strokeWidth: 1.75 }) }), children: [(0, jsx_runtime_1.jsx)(menu_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { size: 15, strokeWidth: 1.75 }), shortcut: "\u2318C", children: t.copyRecordLink }), (0, jsx_runtime_1.jsx)(menu_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 15, strokeWidth: 1.75 }), children: t.addToList }), (0, jsx_runtime_1.jsx)(menu_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Star, { size: 15, strokeWidth: 1.75 }), onSelect: () => setFavorite((f) => !f), children: favorite ? t.removeFromFavourites : t.addToFavourites }), (0, jsx_runtime_1.jsx)(menu_1.MenuSeparator, {}), (0, jsx_runtime_1.jsx)(menu_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Trash2, { size: 15, strokeWidth: 1.75 }), danger: true, shortcut: "\u232B", children: t.deleteRecord })] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-body", children: [(0, jsx_runtime_1.jsxs)("aside", { className: "crisp-recordpage-details", style: { width: detailsW }, children: [(0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-entity", children: [entity?.avatar ? ((0, jsx_runtime_1.jsx)("img", { className: "crisp-recordpage-entity-logo", src: entity.avatar, alt: "" })) : ((0, jsx_runtime_1.jsx)(avatar_1.Avatar, { size: "lg", shape: "rounded", tone: "brand", children: name.charAt(0) })), (0, jsx_runtime_1.jsx)("span", { className: "crisp-recordpage-entity-name", children: name }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-entity-iconbtn", "aria-label": t.editRecord, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Pencil, { size: 15, strokeWidth: 1.75 }) }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-entity-iconbtn", "data-active": favorite ? "" : undefined, "aria-pressed": favorite, onClick: () => setFavorite((f) => !f), "aria-label": favorite ? t.removeFromFavourites : t.addToFavourites, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Star, { size: 15, strokeWidth: 1.75 }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-quickactions", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-recordpage-compose", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Mail, { size: 16, strokeWidth: 1.75 }), t.composeEmail] }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-quickbtn", "aria-label": t.copyRecordLink, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { size: 15, strokeWidth: 1.75 }) }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-quickbtn", "aria-label": t.logANote, children: (0, jsx_runtime_1.jsx)(lucide_react_1.FileText, { size: 15, strokeWidth: 1.75 }) }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-quickbtn", "aria-label": t.linkRecords, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Share2, { size: 15, strokeWidth: 1.75 }) }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-recordpage-quickbtn", "aria-label": t.createATask, children: (0, jsx_runtime_1.jsx)(lucide_react_1.SquareCheck, { size: 15, strokeWidth: 1.75 }) })] }), (0, jsx_runtime_1.jsx)(RecordDetails, { record: record, columns: columns, sections: sections, onEdit: onEdit, labels: labels }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-recordpage-section", children: [(0, jsx_runtime_1.jsx)(SectionHead, { title: t.tabs.lists, action: (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-recordpage-addbtn", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 14, strokeWidth: 2 }), t.addToList] }) }), (0, jsx_runtime_1.jsx)("div", { className: "crisp-recordpage-emptystate", children: t.noLists })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "crisp-recordpage-resizer", "data-active": resizing ? "" : undefined, role: "separator", "aria-orientation": "vertical", "aria-label": t.resizeDetails, "aria-valuenow": Math.round(detailsW), "aria-valuemin": DETAILS_MIN_W, "aria-valuemax": DETAILS_MAX_W, tabIndex: 0, onPointerDown: onResizeDown, onPointerMove: onResizeMove, onPointerUp: onResizeUp, onKeyDown: (e) => {
|
|
663
678
|
if (e.key !== "ArrowLeft" && e.key !== "ArrowRight")
|
|
664
679
|
return;
|
|
665
680
|
// The pointer drag learned its direction in #212; this did not.
|
|
@@ -668,7 +683,9 @@ function RecordPage({ record, columns, collection = "Records", labels, onBack, o
|
|
|
668
683
|
// half-conversion the drag had, one handler away (#255).
|
|
669
684
|
const rtl = (0, core_1.isRtlElement)(e.currentTarget);
|
|
670
685
|
const grow = e.key === (rtl ? "ArrowLeft" : "ArrowRight");
|
|
671
|
-
setDetailsW((w) => grow
|
|
686
|
+
setDetailsW((w) => grow
|
|
687
|
+
? Math.min(DETAILS_MAX_W, w + 16)
|
|
688
|
+
: Math.max(DETAILS_MIN_W, w - 16));
|
|
672
689
|
} }), (0, jsx_runtime_1.jsx)("main", { className: "crisp-recordpage-main", children: (0, jsx_runtime_1.jsx)(tabs_1.Tabs, { tabs: effectiveTabs, defaultValue: tabsProp ? defaultTab : "overview", "aria-label": `${name} record`, children: effectivePanel }) })] })] }));
|
|
673
690
|
}
|
|
674
691
|
RecordPage.displayName = "RecordPage";
|