@crispy-seed/data-table 0.1.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/LICENSE +201 -0
- package/NOTICE +30 -0
- package/README.md +103 -0
- package/dist/DataTable-12s-8LMBtS2u.cjs +1532 -0
- package/dist/DataTable-12s-Bd20OuMs.js +1482 -0
- package/dist/DataTable-12s-Zml1x9Kr-12s-CTRzgvMT.cjs +161 -0
- package/dist/DataTable-12s-Zml1x9Kr-12s-Coi-3lUa.js +153 -0
- package/dist/Menu-12s-Db_zr1AP.cjs +104 -0
- package/dist/Menu-12s-Di5JADW4.js +78 -0
- package/dist/Select-12s-1Uh7XbkG.js +219 -0
- package/dist/Select-12s-D8DdKT-U.cjs +250 -0
- package/dist/body-cells-12s-BnOVUTKN.js +453 -0
- package/dist/body-cells-12s-BoOTcg-l.cjs +462 -0
- package/dist/column-calc-12s-C6IPSOaF.js +129 -0
- package/dist/column-calc-12s-CKuSpe-l.cjs +149 -0
- package/dist/column-layout-12s-CTu5yT_D.cjs +120 -0
- package/dist/column-layout-12s-s7wnxkMN.js +99 -0
- package/dist/column-menu-12s-BPE9N1gs.cjs +427 -0
- package/dist/column-menu-12s-mRBk-4oa.js +407 -0
- package/dist/data-table-recipe.css +442 -0
- package/dist/data-table-recipe.layered.css +505 -0
- package/dist/editors-12s-BO9Mp034.js +525 -0
- package/dist/editors-12s-DO8TZkYV.cjs +555 -0
- package/dist/index.cjs +14 -0
- package/dist/index.d.ts +323 -0
- package/dist/index.js +10 -0
- package/dist/resize-12s-jQY-PX67.cjs +58 -0
- package/dist/resize-12s-nsMvrmLt.js +58 -0
- package/dist/states-12s-CLO_uVue.cjs +125 -0
- package/dist/states-12s-DEFSxJCO.js +122 -0
- package/dist/styles.css +14660 -0
- package/dist/toolbar-12s-AVU-sbDW.js +69 -0
- package/dist/toolbar-12s-CaLgJrDo.cjs +71 -0
- package/dist/useDataTable-12s-BHiDUubw-12s-CBeCwTe7.js +61 -0
- package/dist/useDataTable-12s-BHiDUubw-12s-Dgvt7XDk.cjs +61 -0
- package/dist/useDataTableColumnCalc-12s-DTQQTtEJ-12s-CvD14JYo.cjs +207 -0
- package/dist/useDataTableColumnCalc-12s-DTQQTtEJ-12s-DsEse3uq.js +183 -0
- package/dist/useDataTableColumns-12s-Cn2ZAzFL-12s-CD6goR59.js +289 -0
- package/dist/useDataTableColumns-12s-Cn2ZAzFL-12s-CUk_CpYT.cjs +292 -0
- package/dist/useDataTableEdit-12s-9Wb_UCrN-12s-BoOHq3GB.js +98 -0
- package/dist/useDataTableEdit-12s-9Wb_UCrN-12s-De6YHBba.cjs +98 -0
- package/dist/useDataTableFilter-12s-ZzbmWMin-12s-CWyBeFna.js +74 -0
- package/dist/useDataTableFilter-12s-ZzbmWMin-12s-lpjzZY3_.cjs +74 -0
- package/dist/useDataTableInfiniteScroll-12s-8ZG31URd-12s-BexjP6iO.js +104 -0
- package/dist/useDataTableInfiniteScroll-12s-8ZG31URd-12s-Bt8gojr9.cjs +104 -0
- package/dist/useDataTableRow-12s-CPYaDa1p-12s-BmUSAnPe.js +30 -0
- package/dist/useDataTableRow-12s-CPYaDa1p-12s-D-DRjwAe.cjs +30 -0
- package/dist/useDataTableScroll-12s-BKDCr0en-12s-C7f2vHeG.js +61 -0
- package/dist/useDataTableScroll-12s-BKDCr0en-12s-CUvUYMtt.cjs +61 -0
- package/dist/useDataTableSearch-12s-Ck3iWcpX-12s-B-65V6gH.js +37 -0
- package/dist/useDataTableSearch-12s-Ck3iWcpX-12s-DhVfN2Hq.cjs +37 -0
- package/dist/useDataTableSelection-12s-BIDtiRQq-12s-IS__VAnU.cjs +71 -0
- package/dist/useDataTableSelection-12s-BIDtiRQq-12s-O6M_BhrH.js +71 -0
- package/dist/useDataTableSort-12s-DvJYtmeS-12s-C5VGnsq4.cjs +78 -0
- package/dist/useDataTableSort-12s-DvJYtmeS-12s-DABSNt6U.js +78 -0
- package/package.json +78 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
function __insertCSS(code) {
|
|
3
|
+
if (!code || typeof document == 'undefined') return
|
|
4
|
+
let head = document.head || document.getElementsByTagName('head')[0]
|
|
5
|
+
let style = document.createElement('style')
|
|
6
|
+
style.type = 'text/css'
|
|
7
|
+
head.appendChild(style)
|
|
8
|
+
;style.styleSheet ? (style.styleSheet.cssText = code) : style.appendChild(document.createTextNode(code))
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
12
|
+
import { dataAttr } from '@seed-design/dom-utils';
|
|
13
|
+
import { forwardRef } from 'react';
|
|
14
|
+
import { c as createSlotRecipeContext, b as clsx, d as IconCheckmarkLine_default, C as CheckboxRoot, e as CheckboxControl, f as CheckboxIndicator, g as CheckboxHiddenInput, D as DataTableCell, h as getColumnValue } from './DataTable-12s-Bd20OuMs.js';
|
|
15
|
+
import { Image } from '@seed-design/react-image';
|
|
16
|
+
import { Primitive } from '@seed-design/react-primitive';
|
|
17
|
+
import { avatar } from '@seed-design/css/recipes/avatar';
|
|
18
|
+
import '@seed-design/css/recipes/avatar-stack';
|
|
19
|
+
import { badge } from '@seed-design/css/recipes/badge';
|
|
20
|
+
import { u as useEffectiveColumns, s as stickyProps } from './column-layout-12s-s7wnxkMN.js';
|
|
21
|
+
import { S as SwitchEditor, r as resolveEditValue, R as RatingEditor, C as CheckboxEditor, a as SelectEditor, b as ReferenceEditor, E as EditError, D as DateEditor, T as TextEditor } from './editors-12s-BO9Mp034.js';
|
|
22
|
+
import { u as useDataTableContext } from './DataTable-12s-Zml1x9Kr-12s-Coi-3lUa.js';
|
|
23
|
+
|
|
24
|
+
const { withProvider, withContext } = createSlotRecipeContext(avatar);
|
|
25
|
+
const AvatarRoot = withProvider(Image.Root, "root");
|
|
26
|
+
const AvatarImage = withContext(Image.Content, "image");
|
|
27
|
+
const AvatarFallback = withContext(Image.Fallback, "fallback");
|
|
28
|
+
withContext(Primitive.div, "badge");
|
|
29
|
+
|
|
30
|
+
const Badge = /*#__PURE__*/ forwardRef(({ className, children, ...props }, ref)=>{
|
|
31
|
+
const [variantProps, restProps] = badge.splitVariantProps(props);
|
|
32
|
+
const { root, label } = badge(variantProps);
|
|
33
|
+
return /*#__PURE__*/ jsx(Primitive.span, {
|
|
34
|
+
className: clsx(root, className),
|
|
35
|
+
...restProps,
|
|
36
|
+
ref: ref,
|
|
37
|
+
children: /*#__PURE__*/ jsx(Primitive.span, {
|
|
38
|
+
className: label,
|
|
39
|
+
children: children
|
|
40
|
+
})
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
Badge.displayName = "Badge";
|
|
44
|
+
|
|
45
|
+
// Attio cell-type renderers, built from seed's own components -- not exported from
|
|
46
|
+
// the package's public surface (kept alongside DataTable.tsx as an implementation
|
|
47
|
+
// detail, the way Select keeps `InternalIcon` under `components/private`). Each
|
|
48
|
+
// renderer takes the raw column value and the table's resolved recipe classNames,
|
|
49
|
+
// and returns `null` for an empty value: Attio's own empty cell is genuinely blank,
|
|
50
|
+
// no placeholder character, for any type (crisp's datatable.tsx, #412).
|
|
51
|
+
// seed's `CheckboxIndicator` renders exactly what its `checked` prop is -- it does not
|
|
52
|
+
// supply a checkmark on its own. `checked={null}` (this file's own pre-fix state)
|
|
53
|
+
// therefore rendered an empty box even once the value WAS true; every read-only/
|
|
54
|
+
// editable checkbox cell in this component needs a real icon here, the same one the
|
|
55
|
+
// row-selection checkbox already uses (`DataTable.tsx`'s `SELECTION_ICON_SIZE`, 12px).
|
|
56
|
+
const CHECKBOX_CELL_CHECKED_ICON = /*#__PURE__*/ jsx(IconCheckmarkLine_default, {
|
|
57
|
+
size: 12
|
|
58
|
+
});
|
|
59
|
+
// The 6 tones Badge ships (`@seed-design/css/recipes/badge`) -- not Attio's own
|
|
60
|
+
// wider palette (crisp's tag/status cells hash across a measured 7- or 12-colour
|
|
61
|
+
// set it defines itself), because this component builds cell chrome ONLY from
|
|
62
|
+
// seed's already-shipped primitives rather than adding a parallel palette. Same
|
|
63
|
+
// stable-hash approach as crisp's own `toneFor` (multiply-and-add over char codes),
|
|
64
|
+
// just over seed's tone list instead of crisp's.
|
|
65
|
+
const BADGE_TONES = [
|
|
66
|
+
"neutral",
|
|
67
|
+
"brand",
|
|
68
|
+
"informative",
|
|
69
|
+
"positive",
|
|
70
|
+
"warning",
|
|
71
|
+
"critical"
|
|
72
|
+
];
|
|
73
|
+
function toneFor(value) {
|
|
74
|
+
let hash = 0;
|
|
75
|
+
for(let index = 0; index < value.length; index++){
|
|
76
|
+
hash = hash * 31 + value.charCodeAt(index) >>> 0;
|
|
77
|
+
}
|
|
78
|
+
return BADGE_TONES[hash % BADGE_TONES.length];
|
|
79
|
+
}
|
|
80
|
+
function initialsFor(name) {
|
|
81
|
+
const parts = name.trim().split(/\s+/);
|
|
82
|
+
return ((parts[0]?.[0] ?? "") + (parts[1]?.[0] ?? "")).toUpperCase() || "?";
|
|
83
|
+
}
|
|
84
|
+
function formatNumberCell(value, locale) {
|
|
85
|
+
return typeof value === "number" ? value.toLocaleString(locale) : null;
|
|
86
|
+
}
|
|
87
|
+
function formatCurrencyCell(value, symbol, locale) {
|
|
88
|
+
return typeof value === "number" ? `${symbol}${value.toLocaleString(locale)}` : null;
|
|
89
|
+
}
|
|
90
|
+
function toDate(value) {
|
|
91
|
+
const date = value instanceof Date ? value : typeof value === "string" ? new Date(value) : null;
|
|
92
|
+
return date && !Number.isNaN(date.getTime()) ? date : null;
|
|
93
|
+
}
|
|
94
|
+
/** `<input type="date">`'s own value shape (`yyyy-mm-dd`) -- editors.tsx's plain
|
|
95
|
+
* `cellType: "date"` inline editor reads/writes exactly this string, native to the
|
|
96
|
+
* browser's own date input, so no separate parse/format step is needed on commit. */ function toDateInputValue(value) {
|
|
97
|
+
const date = toDate(value);
|
|
98
|
+
if (!date) return "";
|
|
99
|
+
const pad = (n)=>String(n).padStart(2, "0");
|
|
100
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
|
101
|
+
}
|
|
102
|
+
/** `<input type="datetime-local">`'s own value shape (`yyyy-mm-ddThh:mm`) -- same
|
|
103
|
+
* reasoning as `toDateInputValue` above, one input type over. */ function toDateTimeInputValue(value) {
|
|
104
|
+
const date = toDate(value);
|
|
105
|
+
if (!date) return "";
|
|
106
|
+
const pad = (n)=>String(n).padStart(2, "0");
|
|
107
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
108
|
+
}
|
|
109
|
+
function formatDateCell(value, locale) {
|
|
110
|
+
const date = toDate(value);
|
|
111
|
+
if (!date) return null;
|
|
112
|
+
return new Intl.DateTimeFormat(locale, {
|
|
113
|
+
month: "short",
|
|
114
|
+
day: "numeric",
|
|
115
|
+
year: "numeric"
|
|
116
|
+
}).format(date);
|
|
117
|
+
}
|
|
118
|
+
function formatDateTimeCell(value, locale) {
|
|
119
|
+
const date = toDate(value);
|
|
120
|
+
if (!date) return null;
|
|
121
|
+
return new Intl.DateTimeFormat(locale, {
|
|
122
|
+
month: "short",
|
|
123
|
+
day: "numeric",
|
|
124
|
+
year: "numeric",
|
|
125
|
+
hour: "numeric",
|
|
126
|
+
minute: "2-digit"
|
|
127
|
+
}).format(date);
|
|
128
|
+
}
|
|
129
|
+
function EntityCell({ value, className, nameClassName }) {
|
|
130
|
+
const entity = typeof value === "object" && value !== null ? value : {
|
|
131
|
+
name: String(value ?? "")
|
|
132
|
+
};
|
|
133
|
+
if (!entity.name) return null;
|
|
134
|
+
return /*#__PURE__*/ jsxs("span", {
|
|
135
|
+
className: className,
|
|
136
|
+
children: [
|
|
137
|
+
/*#__PURE__*/ jsxs(AvatarRoot, {
|
|
138
|
+
size: "20",
|
|
139
|
+
children: [
|
|
140
|
+
entity.avatar && /*#__PURE__*/ jsx(AvatarImage, {
|
|
141
|
+
src: entity.avatar,
|
|
142
|
+
alt: ""
|
|
143
|
+
}),
|
|
144
|
+
/*#__PURE__*/ jsx(AvatarFallback, {
|
|
145
|
+
children: initialsFor(entity.name)
|
|
146
|
+
})
|
|
147
|
+
]
|
|
148
|
+
}),
|
|
149
|
+
/*#__PURE__*/ jsx("span", {
|
|
150
|
+
className: nameClassName,
|
|
151
|
+
children: entity.name
|
|
152
|
+
})
|
|
153
|
+
]
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function TagsCell({ value, className }) {
|
|
157
|
+
const tags = Array.isArray(value) ? value : [];
|
|
158
|
+
if (!tags.length) return null;
|
|
159
|
+
return /*#__PURE__*/ jsx("span", {
|
|
160
|
+
className: className,
|
|
161
|
+
children: tags.map((tag)=>/*#__PURE__*/ jsx(Badge, {
|
|
162
|
+
tone: toneFor(tag),
|
|
163
|
+
variant: "weak",
|
|
164
|
+
size: "medium",
|
|
165
|
+
children: tag
|
|
166
|
+
}, tag))
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
function StatusCell({ value }) {
|
|
170
|
+
const status = value == null ? "" : String(value);
|
|
171
|
+
if (!status) return null;
|
|
172
|
+
return /*#__PURE__*/ jsx(Badge, {
|
|
173
|
+
tone: toneFor(status),
|
|
174
|
+
variant: "weak",
|
|
175
|
+
size: "medium",
|
|
176
|
+
children: status
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
function LinkCell({ column, value, className }) {
|
|
180
|
+
const text = value == null ? "" : String(value);
|
|
181
|
+
if (!text) return null;
|
|
182
|
+
const isUrl = column.type === "url";
|
|
183
|
+
const href = isUrl ? /^https?:\/\//.test(text) ? text : `https://${text}` : `mailto:${text}`;
|
|
184
|
+
return /*#__PURE__*/ jsx("a", {
|
|
185
|
+
className: className,
|
|
186
|
+
href: href,
|
|
187
|
+
target: isUrl ? "_blank" : undefined,
|
|
188
|
+
rel: isUrl ? "noreferrer" : undefined,
|
|
189
|
+
// A link cell points somewhere other than "select this row" -- its own
|
|
190
|
+
// navigation must not also fire a row click handler.
|
|
191
|
+
onClick: (event)=>event.stopPropagation(),
|
|
192
|
+
children: text
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
// Attio's own measured 5-point star path (crisp's `RATING_STAR_D`, traced from the
|
|
196
|
+
// live widget's SVG) -- reused verbatim rather than a generic star glyph, so a
|
|
197
|
+
// rating cell's silhouette matches Attio exactly instead of approximating it. Exported
|
|
198
|
+
// so editors.tsx's interactive `RatingEditor` (an `editable` rating column, clicking a
|
|
199
|
+
// star commits) draws the identical silhouette rather than a second, slightly
|
|
200
|
+
// different one.
|
|
201
|
+
const RATING_STAR_D = "M7.32203 2.81085C7.65793 1.97438 8.84207 1.97438 9.17797 2.81085L10.0851 5.06967C10.2281 5.42587 10.5624 5.66876 10.9454 5.69473L13.3739 5.8594C14.2733 5.92038 14.6392 7.04656 13.9475 7.62451L12.0795 9.18521C11.7849 9.43132 11.6572 9.82433 11.7509 10.1966L12.3447 12.5572C12.5647 13.4313 11.6067 14.1273 10.8433 13.6481L8.78171 12.3538C8.45661 12.1497 8.04339 12.1497 7.71829 12.3538L5.65675 13.6481C4.89333 14.1273 3.93534 13.4313 4.15526 12.5572L4.74911 10.1966C4.84276 9.82433 4.71507 9.43132 4.4205 9.18521L2.55254 7.62451C1.86081 7.04656 2.22673 5.92038 3.12606 5.8594L5.55463 5.69473C5.9376 5.66876 6.27191 5.42587 6.41495 5.06967L7.32203 2.81085Z";
|
|
202
|
+
// Filled = the same measured Attio brand blue the selected-row tint uses
|
|
203
|
+
// (`data-table.ts`'s `ATTIO_BRAND_BLUE`); empty = crisp's own measured
|
|
204
|
+
// `rgba(0,0,0,0.1)`. Literal, not a recipe token -- see that file's comment on why.
|
|
205
|
+
const RATING_FILLED = "#0298d9";
|
|
206
|
+
const RATING_EMPTY = "rgba(0, 0, 0, 0.1)";
|
|
207
|
+
function RatingCell({ value, maxRating = 5 }) {
|
|
208
|
+
const rating = typeof value === "number" ? value : Number(value);
|
|
209
|
+
if (!rating || Number.isNaN(rating)) return null;
|
|
210
|
+
return /*#__PURE__*/ jsx("span", {
|
|
211
|
+
style: {
|
|
212
|
+
display: "inline-flex",
|
|
213
|
+
alignItems: "center",
|
|
214
|
+
gap: 2
|
|
215
|
+
},
|
|
216
|
+
children: Array.from({
|
|
217
|
+
length: maxRating
|
|
218
|
+
}, (_, index)=>// biome-ignore lint/suspicious/noArrayIndexKey: a fixed-length star row has no other identity
|
|
219
|
+
/*#__PURE__*/ jsx("svg", {
|
|
220
|
+
width: 16,
|
|
221
|
+
height: 16,
|
|
222
|
+
viewBox: "0 0 16 16",
|
|
223
|
+
fill: "none",
|
|
224
|
+
role: "presentation",
|
|
225
|
+
"aria-hidden": "true",
|
|
226
|
+
children: /*#__PURE__*/ jsx("path", {
|
|
227
|
+
d: RATING_STAR_D,
|
|
228
|
+
fill: index < rating ? RATING_FILLED : RATING_EMPTY
|
|
229
|
+
})
|
|
230
|
+
}, index))
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
/** `type: "checkbox"`'s READ-ONLY display -- a disabled seed `Checkbox` reflecting
|
|
234
|
+
* the raw boolean, so a non-`editable` checkbox column still reads as a checkbox
|
|
235
|
+
* (crisp's own measured shape, distinct from `switch`/`rating`'s toggle/star), not a
|
|
236
|
+
* bare "true"/"false" string. The `editable` case (a live, clickable checkbox) is
|
|
237
|
+
* `editors.tsx`'s `CheckboxEditor` -- this renderer never handles a click. */ function CheckboxCell({ value }) {
|
|
238
|
+
const checked = value === true || value === "true";
|
|
239
|
+
return /*#__PURE__*/ jsxs(CheckboxRoot, {
|
|
240
|
+
checked: checked,
|
|
241
|
+
disabled: true,
|
|
242
|
+
tabIndex: -1,
|
|
243
|
+
children: [
|
|
244
|
+
/*#__PURE__*/ jsx(CheckboxControl, {
|
|
245
|
+
children: /*#__PURE__*/ jsx(CheckboxIndicator, {
|
|
246
|
+
checked: CHECKBOX_CELL_CHECKED_ICON
|
|
247
|
+
})
|
|
248
|
+
}),
|
|
249
|
+
/*#__PURE__*/ jsx(CheckboxHiddenInput, {
|
|
250
|
+
"aria-label": "Value"
|
|
251
|
+
})
|
|
252
|
+
]
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** `editable` + one of these shapes needs no double-click gate and no separate rest
|
|
257
|
+
* display -- interacting with the widget itself IS the commit gesture (crisp's own
|
|
258
|
+
* #453/#760/#761: `switch`/`rating`/`checkbox` never had a meaningfully different
|
|
259
|
+
* "rest" state to show). Every other `editable` column opens on double-click. */ function isAlwaysLiveEditable(column) {
|
|
260
|
+
if (!column.editable) return false;
|
|
261
|
+
return column.editor === "switch" || column.type === "rating" || column.type === "checkbox";
|
|
262
|
+
}
|
|
263
|
+
function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyFirst, stickyLast }) {
|
|
264
|
+
const effective = useEffectiveColumns(columns);
|
|
265
|
+
const { startEdit } = useDataTableContext();
|
|
266
|
+
return /*#__PURE__*/ jsx(Fragment, {
|
|
267
|
+
children: effective.map(({ column }, index)=>{
|
|
268
|
+
const isFirst = index === 0;
|
|
269
|
+
const isLast = index === effective.length - 1;
|
|
270
|
+
const sticky = stickyProps({
|
|
271
|
+
selectable,
|
|
272
|
+
stickyFirst,
|
|
273
|
+
stickyLast,
|
|
274
|
+
isSelectionCell: false,
|
|
275
|
+
isFirst,
|
|
276
|
+
isLast
|
|
277
|
+
});
|
|
278
|
+
// A gated `editable` column (everything except the always-live widgets)
|
|
279
|
+
// opens on double-click -- Attio's own measured gesture (crisp's #411),
|
|
280
|
+
// matched here rather than a single click, which stays "select this cell"
|
|
281
|
+
// in crisp's own spreadsheet model and would otherwise be indistinguishable
|
|
282
|
+
// from this table's plain row click.
|
|
283
|
+
const gated = column.editable && !isAlwaysLiveEditable(column);
|
|
284
|
+
return /*#__PURE__*/ jsx(DataTableCell, {
|
|
285
|
+
"data-numeric": dataAttr(column.type === "number" || column.type === "currency"),
|
|
286
|
+
"data-editable": dataAttr(!!column.editable),
|
|
287
|
+
"data-sticky": sticky["data-sticky"],
|
|
288
|
+
"data-sticky-edge": sticky["data-sticky-edge"],
|
|
289
|
+
"data-sticky-edge-end": sticky["data-sticky-edge-end"],
|
|
290
|
+
style: sticky.style,
|
|
291
|
+
onDoubleClick: gated ? ()=>startEdit(row.id, column.key) : undefined,
|
|
292
|
+
children: /*#__PURE__*/ jsx(CellContent, {
|
|
293
|
+
column: column,
|
|
294
|
+
row: row,
|
|
295
|
+
rowId: row.id,
|
|
296
|
+
classNames: classNames,
|
|
297
|
+
locale: locale
|
|
298
|
+
})
|
|
299
|
+
}, column.key);
|
|
300
|
+
})
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Dispatches to whichever of cells.tsx's static renderers or editors.tsx's live
|
|
305
|
+
* editors applies to THIS column/row right now -- always-live first (no rest state to
|
|
306
|
+
* fall back to), then a gated editor while the cell is mid-edit, else the plain
|
|
307
|
+
* display (a custom `render` wins there, same as before `editable` existed; it never
|
|
308
|
+
* overrides an actual editing/always-live state, matching crisp's own split between
|
|
309
|
+
* `renderTyped`'s rest-state branch and the editing branches above it).
|
|
310
|
+
*/ function CellContent({ column, row, rowId, classNames, locale }) {
|
|
311
|
+
const { isEditing, isPending, getEditError, commitEdit, cancelEdit } = useDataTableContext();
|
|
312
|
+
const rawValue = getColumnValue(column, row);
|
|
313
|
+
const pending = isPending(rowId, column.key);
|
|
314
|
+
const error = column.editable ? getEditError(rowId, column.key) : null;
|
|
315
|
+
const commit = (value)=>commitEdit(rowId, column.key, value);
|
|
316
|
+
const cancel = ()=>cancelEdit();
|
|
317
|
+
let node;
|
|
318
|
+
if (column.editable && column.editor === "switch") {
|
|
319
|
+
node = /*#__PURE__*/ jsx(SwitchEditor, {
|
|
320
|
+
column: column,
|
|
321
|
+
value: resolveEditValue(column, row, rawValue),
|
|
322
|
+
pending: pending,
|
|
323
|
+
onCommit: commit
|
|
324
|
+
});
|
|
325
|
+
} else if (column.editable && column.type === "rating") {
|
|
326
|
+
node = /*#__PURE__*/ jsx(RatingEditor, {
|
|
327
|
+
column: column,
|
|
328
|
+
value: resolveEditValue(column, row, rawValue),
|
|
329
|
+
pending: pending,
|
|
330
|
+
onCommit: commit
|
|
331
|
+
});
|
|
332
|
+
} else if (column.editable && column.type === "checkbox") {
|
|
333
|
+
node = /*#__PURE__*/ jsx(CheckboxEditor, {
|
|
334
|
+
column: column,
|
|
335
|
+
value: resolveEditValue(column, row, rawValue),
|
|
336
|
+
pending: pending,
|
|
337
|
+
onCommit: commit
|
|
338
|
+
});
|
|
339
|
+
} else if (column.editable && isEditing(rowId, column.key)) {
|
|
340
|
+
if (column.editor === "select") {
|
|
341
|
+
node = /*#__PURE__*/ jsx(SelectEditor, {
|
|
342
|
+
column: column,
|
|
343
|
+
value: resolveEditValue(column, row, rawValue),
|
|
344
|
+
pending: pending,
|
|
345
|
+
onCommit: commit,
|
|
346
|
+
onCancel: cancel
|
|
347
|
+
});
|
|
348
|
+
} else if (column.editor === "reference" || column.editor === "actor") {
|
|
349
|
+
node = /*#__PURE__*/ jsx(ReferenceEditor, {
|
|
350
|
+
column: column,
|
|
351
|
+
value: resolveEditValue(column, row, rawValue),
|
|
352
|
+
pending: pending,
|
|
353
|
+
onCommit: commit,
|
|
354
|
+
onCancel: cancel
|
|
355
|
+
});
|
|
356
|
+
} else if (column.cellType === "date" || column.cellType === "datetime") {
|
|
357
|
+
node = /*#__PURE__*/ jsx(DateEditor, {
|
|
358
|
+
column: column,
|
|
359
|
+
value: rawValue,
|
|
360
|
+
pending: pending,
|
|
361
|
+
onCommit: commit,
|
|
362
|
+
onCancel: cancel
|
|
363
|
+
});
|
|
364
|
+
} else {
|
|
365
|
+
node = /*#__PURE__*/ jsx(TextEditor, {
|
|
366
|
+
column: column,
|
|
367
|
+
value: rawValue,
|
|
368
|
+
pending: pending,
|
|
369
|
+
onCommit: commit,
|
|
370
|
+
onCancel: cancel
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
} else {
|
|
374
|
+
node = /*#__PURE__*/ jsx(DisplayCellContent, {
|
|
375
|
+
column: column,
|
|
376
|
+
row: row,
|
|
377
|
+
value: rawValue,
|
|
378
|
+
classNames: classNames,
|
|
379
|
+
locale: locale
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
383
|
+
children: [
|
|
384
|
+
node,
|
|
385
|
+
error && /*#__PURE__*/ jsx(EditError, {
|
|
386
|
+
message: error
|
|
387
|
+
})
|
|
388
|
+
]
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
// The plain (non-editing) Attio cell-type renderer -- unchanged from before this
|
|
392
|
+
// table grew inline editing, just renamed (it used to be the whole of `CellContent`)
|
|
393
|
+
// since that name now belongs to the dispatcher above.
|
|
394
|
+
function DisplayCellContent({ column, row, value, classNames, locale }) {
|
|
395
|
+
if (column.render) return /*#__PURE__*/ jsx(Fragment, {
|
|
396
|
+
children: column.render(row)
|
|
397
|
+
});
|
|
398
|
+
switch(column.type){
|
|
399
|
+
case "entity":
|
|
400
|
+
return /*#__PURE__*/ jsx(EntityCell, {
|
|
401
|
+
value: value,
|
|
402
|
+
className: classNames.entity,
|
|
403
|
+
nameClassName: classNames.entityName
|
|
404
|
+
});
|
|
405
|
+
case "url":
|
|
406
|
+
case "email":
|
|
407
|
+
return /*#__PURE__*/ jsx(LinkCell, {
|
|
408
|
+
column: column,
|
|
409
|
+
value: value,
|
|
410
|
+
className: classNames.link
|
|
411
|
+
});
|
|
412
|
+
case "tags":
|
|
413
|
+
return /*#__PURE__*/ jsx(TagsCell, {
|
|
414
|
+
value: value,
|
|
415
|
+
className: classNames.tagList
|
|
416
|
+
});
|
|
417
|
+
case "status":
|
|
418
|
+
return /*#__PURE__*/ jsx(StatusCell, {
|
|
419
|
+
value: value
|
|
420
|
+
});
|
|
421
|
+
case "number":
|
|
422
|
+
return /*#__PURE__*/ jsx(Fragment, {
|
|
423
|
+
children: formatNumberCell(value, locale)
|
|
424
|
+
});
|
|
425
|
+
case "currency":
|
|
426
|
+
return /*#__PURE__*/ jsx(Fragment, {
|
|
427
|
+
children: formatCurrencyCell(value, column.symbol ?? "$", locale)
|
|
428
|
+
});
|
|
429
|
+
case "date":
|
|
430
|
+
return /*#__PURE__*/ jsx(Fragment, {
|
|
431
|
+
children: formatDateCell(value, locale)
|
|
432
|
+
});
|
|
433
|
+
case "datetime":
|
|
434
|
+
return /*#__PURE__*/ jsx(Fragment, {
|
|
435
|
+
children: formatDateTimeCell(value, locale)
|
|
436
|
+
});
|
|
437
|
+
case "rating":
|
|
438
|
+
return /*#__PURE__*/ jsx(RatingCell, {
|
|
439
|
+
value: value,
|
|
440
|
+
maxRating: column.maxRating
|
|
441
|
+
});
|
|
442
|
+
case "checkbox":
|
|
443
|
+
return /*#__PURE__*/ jsx(CheckboxCell, {
|
|
444
|
+
value: value
|
|
445
|
+
});
|
|
446
|
+
default:
|
|
447
|
+
return /*#__PURE__*/ jsx(Fragment, {
|
|
448
|
+
children: value == null ? null : String(value)
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
export { AvatarRoot as A, ColumnBodyCells as C, RATING_FILLED as R, RATING_EMPTY as a, RATING_STAR_D as b, CHECKBOX_CELL_CHECKED_ICON as c, AvatarImage as d, AvatarFallback as e, toDateInputValue as f, toDateTimeInputValue as t };
|