@crisp-ui-kit/crisp 0.50.0 → 0.52.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/composewindow/composewindow.js +144 -0
- package/dist/cjs/components/composewindow/composewindow.recipe.js +45 -0
- package/dist/cjs/components/composewindow/index.js +8 -0
- package/dist/cjs/components/datatable/datatable.js +224 -43
- package/dist/cjs/components/datatable/datatable.recipe.js +37 -3
- package/dist/cjs/components/datatable/index.js +6 -0
- package/dist/cjs/components/datepickerfield/datepickerfield.js +25 -15
- package/dist/cjs/components/datepickerfield/datepickerfield.recipe.js +25 -8
- package/dist/cjs/components/dialog/dialog.recipe.js +9 -1
- package/dist/cjs/components/menu/menu.js +4 -2
- package/dist/cjs/components/multiselect/multiselect.recipe.js +14 -8
- package/dist/cjs/components/select/select.js +2 -1
- package/dist/cjs/components/table/table.recipe.js +12 -3
- package/dist/cjs/components/tabletoolbar/tabletoolbar.chrome.js +1 -1
- package/dist/cjs/components/tabletoolbar/tabletoolbar.js +18 -7
- package/dist/cjs/core/caret-rect.js +73 -0
- package/dist/cjs/core/cell-date.js +11 -0
- package/dist/cjs/core/index.js +8 -1
- package/dist/cjs/core/mention.js +32 -0
- package/dist/cjs/core/use-mention-trigger.js +124 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/product/recordpage/recordpage.js +88 -10
- package/dist/cjs/product/recordpage/recordpage.recipe.js +30 -0
- package/dist/cjs/product/recordpanel/recordpanel.js +11 -29
- package/dist/cjs/product/recordpanel/recordpanel.recipe.js +55 -17
- package/dist/cjs/product/recordstable/editable-field.js +113 -0
- package/dist/cjs/product/recordstable/index.js +4 -1
- package/dist/cjs/product/recordstable/recordstable.js +67 -11
- package/dist/cjs/product/recordstable/recordstable.recipe.js +9 -1
- package/dist/cjs/product/recordstable/recordstable.tag.js +8 -3
- package/dist/cjs/product/richtext/index.js +2 -1
- package/dist/cjs/product/richtext/richtext.js +440 -23
- package/dist/cjs/product/richtext/richtext.recipe.js +59 -9
- package/dist/cjs/product/settingsshell/settingsshell.recipe.js +13 -4
- package/dist/cjs/product/sidebar/sidebar.js +15 -3
- package/dist/cjs/product/sidebar/sidebar.recipe.js +21 -2
- package/dist/composewindow.css +24 -0
- package/dist/composewindow.d.ts +7 -0
- package/dist/composewindow.layered.css +26 -0
- package/dist/datatable.css +33 -14
- package/dist/datatable.layered.css +33 -14
- package/dist/datepickerfield.css +9 -4
- package/dist/datepickerfield.layered.css +9 -4
- package/dist/dialog.css +2 -1
- package/dist/dialog.layered.css +2 -1
- package/dist/esm/components/composewindow/composewindow.js +107 -0
- package/dist/esm/components/composewindow/composewindow.recipe.js +42 -0
- package/dist/esm/components/composewindow/index.js +2 -0
- package/dist/esm/components/datatable/datatable.js +226 -45
- package/dist/esm/components/datatable/datatable.recipe.js +37 -3
- package/dist/esm/components/datatable/index.js +6 -0
- package/dist/esm/components/datepickerfield/datepickerfield.js +26 -16
- package/dist/esm/components/datepickerfield/datepickerfield.recipe.js +25 -8
- package/dist/esm/components/dialog/dialog.recipe.js +9 -1
- package/dist/esm/components/menu/menu.js +4 -2
- package/dist/esm/components/multiselect/multiselect.recipe.js +14 -8
- package/dist/esm/components/select/select.js +2 -1
- package/dist/esm/components/table/table.recipe.js +12 -3
- package/dist/esm/components/tabletoolbar/tabletoolbar.chrome.js +1 -1
- package/dist/esm/components/tabletoolbar/tabletoolbar.js +18 -7
- package/dist/esm/core/caret-rect.js +70 -0
- package/dist/esm/core/cell-date.js +10 -0
- package/dist/esm/core/index.js +4 -1
- package/dist/esm/core/mention.js +29 -0
- package/dist/esm/core/use-mention-trigger.js +88 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/product/recordpage/recordpage.js +89 -11
- package/dist/esm/product/recordpage/recordpage.recipe.js +30 -0
- package/dist/esm/product/recordpanel/index.js +1 -1
- package/dist/esm/product/recordpanel/recordpanel.js +13 -31
- package/dist/esm/product/recordpanel/recordpanel.recipe.js +56 -18
- package/dist/esm/product/recordstable/editable-field.js +76 -0
- package/dist/esm/product/recordstable/index.js +1 -0
- package/dist/esm/product/recordstable/recordstable.js +69 -13
- package/dist/esm/product/recordstable/recordstable.recipe.js +9 -1
- package/dist/esm/product/recordstable/recordstable.tag.js +8 -3
- package/dist/esm/product/richtext/index.js +1 -1
- package/dist/esm/product/richtext/richtext.js +439 -22
- package/dist/esm/product/richtext/richtext.recipe.js +60 -10
- package/dist/esm/product/settingsshell/settingsshell.recipe.js +13 -4
- package/dist/esm/product/sidebar/sidebar.js +15 -3
- package/dist/esm/product/sidebar/sidebar.recipe.js +21 -2
- package/dist/multiselect.css +8 -8
- package/dist/multiselect.layered.css +8 -8
- package/dist/recordpage.css +25 -13
- package/dist/recordpage.layered.css +25 -13
- package/dist/recordpanel.css +43 -20
- package/dist/recordpanel.layered.css +43 -20
- package/dist/recordstable.css +9 -2
- package/dist/recordstable.layered.css +9 -2
- package/dist/richtext.css +31 -5
- package/dist/richtext.layered.css +31 -5
- package/dist/settingsshell.css +2 -2
- package/dist/settingsshell.layered.css +2 -2
- package/dist/sidebar.css +7 -2
- package/dist/sidebar.layered.css +7 -2
- package/dist/styles.css +199 -74
- package/dist/styles.layered.css +199 -74
- package/dist/table.css +4 -2
- package/dist/table.layered.css +4 -2
- package/dist/tabletoolbar.css +1 -1
- package/dist/tabletoolbar.layered.css +1 -1
- package/dist/types/components/composewindow/composewindow.d.ts +80 -0
- package/dist/types/components/composewindow/composewindow.recipe.d.ts +3 -0
- package/dist/types/components/composewindow/index.d.ts +2 -0
- package/dist/types/components/datatable/datatable.d.ts +58 -4
- package/dist/types/components/datatable/index.d.ts +1 -1
- package/dist/types/components/datepickerfield/datepickerfield.d.ts +18 -4
- package/dist/types/components/menu/menu.d.ts +10 -1
- package/dist/types/components/select/select.d.ts +6 -1
- package/dist/types/components/tabletoolbar/tabletoolbar.d.ts +29 -5
- package/dist/types/core/caret-rect.d.ts +16 -0
- package/dist/types/core/cell-date.d.ts +17 -0
- package/dist/types/core/index.d.ts +4 -1
- package/dist/types/core/mention.d.ts +27 -0
- package/dist/types/core/use-mention-trigger.d.ts +41 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/product/recordpage/recordpage.d.ts +59 -1
- package/dist/types/product/recordpanel/index.d.ts +1 -1
- package/dist/types/product/recordpanel/recordpanel.d.ts +81 -17
- package/dist/types/product/recordstable/editable-field.d.ts +48 -0
- package/dist/types/product/recordstable/index.d.ts +1 -0
- package/dist/types/product/recordstable/recordstable.d.ts +29 -0
- package/dist/types/product/recordstable/recordstable.tag.d.ts +8 -3
- package/dist/types/product/richtext/index.d.ts +1 -1
- package/dist/types/product/richtext/richtext.d.ts +168 -7
- package/dist/types/product/sidebar/sidebar.d.ts +60 -4
- package/package.json +6 -1
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.useEditableField = useEditableField;
|
|
37
|
+
exports.editableInputType = editableInputType;
|
|
38
|
+
const React = __importStar(require("react"));
|
|
39
|
+
/**
|
|
40
|
+
* The async-commit state machine behind `RecordPage`'s editable Details
|
|
41
|
+
* column (#431) — the same shape `DataTable`'s own `commitEdit` uses
|
|
42
|
+
* (#385/#430): a sync `onEdit` (returns `undefined`) commits and closes
|
|
43
|
+
* immediately; a Promise-returning `onEdit` keeps the field open and pending
|
|
44
|
+
* while it settles, then either closes it (resolve) or closes it AND
|
|
45
|
+
* reverts while showing the rejection's message (reject). The revert needs
|
|
46
|
+
* no extra code here either: `RecordPage` never mutates `record` itself, so
|
|
47
|
+
* once `editingKey` clears, the field simply renders `record[key]` again —
|
|
48
|
+
* whatever it still says.
|
|
49
|
+
*
|
|
50
|
+
* `RecordPanel` (the peek panel) used to share this hook too, before #448
|
|
51
|
+
* found that Attio's own peek has no editable field at all to attach it to
|
|
52
|
+
* — only `RecordPage`'s Details column does. Kept as its own module rather
|
|
53
|
+
* than folded back into `recordpage.tsx`: a second consumer turning up
|
|
54
|
+
* again is a smaller change than re-extracting it would be.
|
|
55
|
+
*/
|
|
56
|
+
function useEditableField(onEdit) {
|
|
57
|
+
const [editingKey, setEditingKey] = React.useState(null);
|
|
58
|
+
// Set only while an async `onEdit` is in flight -- a sync `onEdit` never
|
|
59
|
+
// touches this.
|
|
60
|
+
const [pendingKey, setPendingKey] = React.useState(null);
|
|
61
|
+
const [error, setError] = React.useState(null);
|
|
62
|
+
// Opening a field's editor also clears any stale error left over from a
|
|
63
|
+
// PREVIOUS failed commit on it -- otherwise a rejection from three edits
|
|
64
|
+
// ago would still be sitting there while the reader tries again.
|
|
65
|
+
const openEditing = React.useCallback((key) => {
|
|
66
|
+
setError(null);
|
|
67
|
+
setEditingKey(key);
|
|
68
|
+
}, []);
|
|
69
|
+
const closeEditing = React.useCallback(() => setEditingKey(null), []);
|
|
70
|
+
const commit = React.useCallback((id, key, value) => {
|
|
71
|
+
setError(null);
|
|
72
|
+
const result = onEdit?.(id, key, value);
|
|
73
|
+
if (result && typeof result.then === "function") {
|
|
74
|
+
setPendingKey(key);
|
|
75
|
+
result.then(() => {
|
|
76
|
+
setPendingKey(null);
|
|
77
|
+
setEditingKey(null);
|
|
78
|
+
}, (err) => {
|
|
79
|
+
setPendingKey(null);
|
|
80
|
+
setEditingKey(null);
|
|
81
|
+
setError({
|
|
82
|
+
key,
|
|
83
|
+
message: err instanceof Error
|
|
84
|
+
? err.message
|
|
85
|
+
: typeof err === "string"
|
|
86
|
+
? err
|
|
87
|
+
: "Could not save",
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
setEditingKey(null);
|
|
93
|
+
}, [onEdit]);
|
|
94
|
+
return { editingKey, pendingKey, error, openEditing, closeEditing, commit };
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Which plain editor a column gets when it's `editable` without an
|
|
98
|
+
* `editor: "select" | "switch"` — identical to `DataTable`'s own
|
|
99
|
+
* `editorFor` (#385): number/currency get a numeric field, date a native
|
|
100
|
+
* date field, everything else (text, entity, tags, url, status, reference)
|
|
101
|
+
* a plain text field. Kept as one function so the two never drift apart.
|
|
102
|
+
*/
|
|
103
|
+
function editableInputType(colType) {
|
|
104
|
+
switch (colType) {
|
|
105
|
+
case "number":
|
|
106
|
+
case "currency":
|
|
107
|
+
return { type: "number", inputMode: "decimal" };
|
|
108
|
+
case "date":
|
|
109
|
+
return { type: "date" };
|
|
110
|
+
default:
|
|
111
|
+
return { type: "text", inputMode: "text" };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.recordstableRecipe = exports.tagTone = exports.RecordsTable = exports.defaultRows = exports.defaultColumns = void 0;
|
|
3
|
+
exports.recordstableRecipe = exports.tagTone = exports.RecordsTable = exports.defaultRows = exports.defaultColumns = exports.useEditableField = exports.editableInputType = void 0;
|
|
4
|
+
var editable_field_1 = require("./editable-field");
|
|
5
|
+
Object.defineProperty(exports, "editableInputType", { enumerable: true, get: function () { return editable_field_1.editableInputType; } });
|
|
6
|
+
Object.defineProperty(exports, "useEditableField", { enumerable: true, get: function () { return editable_field_1.useEditableField; } });
|
|
4
7
|
var recordstable_1 = require("./recordstable");
|
|
5
8
|
Object.defineProperty(exports, "defaultColumns", { enumerable: true, get: function () { return recordstable_1.defaultColumns; } });
|
|
6
9
|
Object.defineProperty(exports, "defaultRows", { enumerable: true, get: function () { return recordstable_1.defaultRows; } });
|
|
@@ -262,15 +262,17 @@ function EntityCell({ value, pinned, onOpenPage, avatarTone = "brand", labels, }
|
|
|
262
262
|
}
|
|
263
263
|
function CellView({ column, row, pinned, onOpenPage, avatarTone = "brand", labels, }) {
|
|
264
264
|
const value = row[column.key];
|
|
265
|
-
// `render` fully owns the cell's content — no empty
|
|
266
|
-
//
|
|
265
|
+
// `render` fully owns the cell's content — no empty fallback, no type
|
|
266
|
+
// renderer; it's the only thing drawn here (see the doc comment on
|
|
267
267
|
// `Column.render`).
|
|
268
268
|
if (column.render)
|
|
269
269
|
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: column.render(value, row) });
|
|
270
270
|
if (value == null ||
|
|
271
271
|
value === "" ||
|
|
272
272
|
(Array.isArray(value) && !value.length)) {
|
|
273
|
-
|
|
273
|
+
// Attio's own empty cell is genuinely blank -- no placeholder character
|
|
274
|
+
// at all (#412).
|
|
275
|
+
return null;
|
|
274
276
|
}
|
|
275
277
|
// `format` keeps the type renderer's chrome below and only replaces the
|
|
276
278
|
// text it displays.
|
|
@@ -313,11 +315,40 @@ function CellView({ column, row, pinned, onOpenPage, avatarTone = "brand", label
|
|
|
313
315
|
function StatusCell({ column, row, onChange, }) {
|
|
314
316
|
return ((0, jsx_runtime_1.jsx)(select_1.Select, { variant: "ghost", "aria-label": column.label, placeholder: "\u2014", value: row[column.key] ?? undefined, onValueChange: onChange, options: column.options ?? [] }));
|
|
315
317
|
}
|
|
318
|
+
// A sentinel that can't collide with a real record id (crisp never generates
|
|
319
|
+
// one, and a consumer's own ids come from their own data store) -- picking
|
|
320
|
+
// this row calls `onCreateReference`, not `onChange` (#449).
|
|
321
|
+
const CREATE_REFERENCE_VALUE = "__crisp_create_reference__";
|
|
322
|
+
/** The 16px avatar Attio's own reference picker draws before every option's
|
|
323
|
+
* label -- a photo when the option carries one, a generic person glyph
|
|
324
|
+
* otherwise (measured live, #449: Attio's own fallback is an icon, not
|
|
325
|
+
* initials -- a different, deliberate choice from the entity cell's own
|
|
326
|
+
* initials fallback elsewhere in this file). */
|
|
327
|
+
function referenceOptionLabel(o) {
|
|
328
|
+
return ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-recordstable-refoption", children: [(0, jsx_runtime_1.jsx)(avatar_1.Avatar, { size: "sm", className: "crisp-recordstable-refoption-avatar", children: o.avatar ? ((0, jsx_runtime_1.jsx)("img", { src: o.avatar, alt: "" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.CircleUserRound, { size: 12, strokeWidth: 1.75, "aria-hidden": "true" })) }), o.label] }));
|
|
329
|
+
}
|
|
316
330
|
function ReferenceCell({ column, row, onChange, labels, }) {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
331
|
+
const [query, setQuery] = React.useState("");
|
|
332
|
+
const options = (column.refOptions ?? []).map((o) => ({
|
|
333
|
+
value: o.value,
|
|
334
|
+
label: referenceOptionLabel(o),
|
|
335
|
+
keywords: o.label,
|
|
336
|
+
}));
|
|
337
|
+
if (column.onCreateReference) {
|
|
338
|
+
options.push({
|
|
339
|
+
value: CREATE_REFERENCE_VALUE,
|
|
340
|
+
label: ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-recordstable-refoption crisp-recordstable-refoption--create", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 16, strokeWidth: 1.75, "aria-hidden": "true" }), `Create ${column.createLabel ?? "record"}`] })),
|
|
341
|
+
// always reachable regardless of the typed query -- it's an action,
|
|
342
|
+
// not a record to filter away
|
|
343
|
+
keywords: query,
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
return ((0, jsx_runtime_1.jsx)(select_1.Select, { variant: "ghost", searchable: true, searchPlaceholder: labels.searchRecordsPlaceholder, onSearchChange: setQuery, "aria-label": column.label, placeholder: labels.setRecordPlaceholder, value: row[column.key] ?? undefined, onValueChange: (v) => {
|
|
347
|
+
if (v === CREATE_REFERENCE_VALUE)
|
|
348
|
+
column.onCreateReference?.(query);
|
|
349
|
+
else
|
|
350
|
+
onChange(v);
|
|
351
|
+
}, options: options }));
|
|
321
352
|
}
|
|
322
353
|
function TagsCell({ column, row, options, onChange, labels, }) {
|
|
323
354
|
const value = row[column.key] ?? [];
|
|
@@ -343,10 +374,35 @@ function TagsCell({ column, row, options, onChange, labels, }) {
|
|
|
343
374
|
const core_2 = require("../../core");
|
|
344
375
|
Object.defineProperty(exports, "formatCellDate", { enumerable: true, get: function () { return core_2.formatCellDate; } });
|
|
345
376
|
Object.defineProperty(exports, "parseCellDate", { enumerable: true, get: function () { return core_2.parseCellDate; } });
|
|
377
|
+
// "1998" for a year-only raw value, "Sep 1998" for year-month, and the full
|
|
378
|
+
// "Sep 4, 1998" only once the raw value actually named a day (#312) --
|
|
379
|
+
// DatePickerField's own default format always prints full precision, since
|
|
380
|
+
// as a general calendar field it has no raw string to read a precision from.
|
|
381
|
+
function formatByPrecision(d, precision) {
|
|
382
|
+
if (precision === "year")
|
|
383
|
+
return String(d.getFullYear());
|
|
384
|
+
return d.toLocaleDateString(undefined, {
|
|
385
|
+
month: "short",
|
|
386
|
+
day: precision === "month" ? undefined : "numeric",
|
|
387
|
+
year: "numeric",
|
|
388
|
+
});
|
|
389
|
+
}
|
|
346
390
|
function DateCell({ column, row, onChange, }) {
|
|
347
391
|
const raw = row[column.key];
|
|
348
392
|
const value = (0, core_2.parseCellDate)(raw);
|
|
349
|
-
|
|
393
|
+
const precision = raw ? (0, core_2.cellDatePrecision)(raw) : "day";
|
|
394
|
+
return ((0, jsx_runtime_1.jsx)(datepickerfield_1.DatePickerField, { variant: "ghost", "aria-label": column.label, value: value,
|
|
395
|
+
// Out of scope for #394 (which added Clear to DatePickerField itself):
|
|
396
|
+
// a cell's OWN clear-to-empty affordance is a different, unmeasured
|
|
397
|
+
// question, and this callback's `string` contract has no "empty" of
|
|
398
|
+
// its own to report yet. Keeps this cell's exact pre-#394 behavior.
|
|
399
|
+
clearable: false,
|
|
400
|
+
// #417: the trigger displays the value at its stored precision
|
|
401
|
+
// (year-only stays year-only) rather than always a full date.
|
|
402
|
+
format: (d) => formatByPrecision(d, precision), onChange: (d) => {
|
|
403
|
+
if (d)
|
|
404
|
+
onChange((0, core_2.formatCellDate)(d));
|
|
405
|
+
} }));
|
|
350
406
|
}
|
|
351
407
|
/**
|
|
352
408
|
* The "New <object>" create modal — measured from a create-record dialog:
|
|
@@ -374,7 +430,7 @@ function CreateRecordDialog({ open, onOpenChange, columns, entityLabel, onCreate
|
|
|
374
430
|
row[col.key] = { name: raw || labels.untitled };
|
|
375
431
|
}
|
|
376
432
|
else if (!raw) {
|
|
377
|
-
// leave empty fields unset so the cell renders
|
|
433
|
+
// leave empty fields unset so the cell renders blank (#412)
|
|
378
434
|
}
|
|
379
435
|
else if (col.type === "tags") {
|
|
380
436
|
row[col.key] = raw
|
|
@@ -406,7 +462,7 @@ function CreateRecordDialog({ open, onOpenChange, columns, entityLabel, onCreate
|
|
|
406
462
|
return ((0, jsx_runtime_1.jsxs)(dialog_1.Dialog, { open: open, onOpenChange: onOpenChange, title: labels.newRecordTitle(entityLabel), icon: EntityIcon ? (0, jsx_runtime_1.jsx)(EntityIcon, { size: 16, strokeWidth: 1.75 }) : undefined, width: 720, children: [(0, jsx_runtime_1.jsx)(dialog_1.DialogBody, { children: columns.map((col, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-dialog-field", children: [(0, jsx_runtime_1.jsx)("label", { className: "crisp-dialog-field-label", htmlFor: `create-${col.key}`, children: col.label }), (0, jsx_runtime_1.jsx)(input_1.Input, { id: `create-${col.key}`, ref: i === 0 ? firstRef : undefined, value: values[col.key] ?? "", onChange: (e) => set(col.key, e.currentTarget.value), placeholder: labels.setFieldPlaceholder(col.label), onKeyDown: (e) => {
|
|
407
463
|
if (e.key === "Enter" && (e.metaKey || e.ctrlKey))
|
|
408
464
|
submit();
|
|
409
|
-
} })] }, col.key))) }), (0, jsx_runtime_1.jsxs)(dialog_1.DialogFooter, { children: [(0, jsx_runtime_1.jsxs)("span", { className: "crisp-dialog-more", children: [
|
|
465
|
+
} })] }, col.key))) }), (0, jsx_runtime_1.jsxs)(dialog_1.DialogFooter, { children: [(0, jsx_runtime_1.jsxs)("span", { className: "crisp-dialog-more", children: [(0, jsx_runtime_1.jsx)(switch_1.Switch, { checked: createMore, onCheckedChange: setCreateMore, "aria-label": labels.createMore }), labels.createMore] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-dialog-submit", onClick: submit, children: [labels.createRecord, (0, jsx_runtime_1.jsxs)("span", { className: "crisp-dialog-submit-key", "aria-hidden": "true", children: [(0, jsx_runtime_1.jsx)("kbd", { children: "\u2318" }), (0, jsx_runtime_1.jsx)("kbd", { children: (0, jsx_runtime_1.jsx)(lucide_react_1.CornerDownLeft, { size: 10, strokeWidth: 2 }) })] })] })] })] }));
|
|
410
466
|
}
|
|
411
467
|
/**
|
|
412
468
|
* A measured-style record grid — fully featured. Toolbar (search / sort status /
|
|
@@ -1073,7 +1129,7 @@ function RecordsTable({ labels, columns: columnsProp = exports.defaultColumns, r
|
|
|
1073
1129
|
setDragCol(col.key);
|
|
1074
1130
|
e.dataTransfer.effectAllowed = "move";
|
|
1075
1131
|
}
|
|
1076
|
-
: undefined, onDragEnd: () => setDragCol(null), onClick: (e) => openColumnMenu(col.key, e.currentTarget), children: [Icon ? (0, jsx_runtime_1.jsx)(Icon, { size:
|
|
1132
|
+
: undefined, onDragEnd: () => setDragCol(null), onClick: (e) => openColumnMenu(col.key, e.currentTarget), children: [Icon ? (0, jsx_runtime_1.jsx)(Icon, { size: 16, strokeWidth: 1.75 }) : null, (0, jsx_runtime_1.jsx)("span", { className: "crisp-recordstable-th-label", children: col.label }), (0, jsx_runtime_1.jsx)("span", { className: "crisp-recordstable-sort", children: (0, jsx_runtime_1.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("path", { d: "m4 6 4 4 4-4" }) }) })] })), openMenu === `col:${col.key}` &&
|
|
1077
1133
|
rootRef.current &&
|
|
1078
1134
|
(0, react_dom_1.createPortal)((0, jsx_runtime_1.jsxs)("div", { ref: menuRef, className: "crisp-recordstable-menu crisp-recordstable-menu--fixed crisp-recordstable-menu--hdr", role: "menu", "aria-label": `${col.label} column`, style: menuPos ?? undefined, onKeyDown: onMenuKeyDown, children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => sortBy(col.key, "asc"), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowUp, { size: 15, strokeWidth: 1.75 }), t.sortAscending] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => sortBy(col.key, "desc"), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowDown, { size: 15, strokeWidth: 1.75 }), t.sortDescending] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-recordstable-menu-item", role: "menuitem", tabIndex: -1, disabled: i <= 1, onClick: () => moveColumn(col.key, -1), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowLeft, { "data-rtl-flip": "", size: 15, strokeWidth: 1.75 }), t.moveLeft] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-recordstable-menu-item", role: "menuitem", tabIndex: -1, disabled: i === 0 || i >= cols.length - 1, onClick: () => moveColumn(col.key, 1), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowRight, { "data-rtl-flip": "", size: 15, strokeWidth: 1.75 }), t.moveRight] }), (0, jsx_runtime_1.jsx)("div", { className: "crisp-recordstable-menu-sep" }), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => {
|
|
1079
1135
|
setRenamingCol(col.key);
|
|
@@ -74,6 +74,14 @@ ${(0, tabletoolbar_chrome_1.toolbarChromeBody)("recordstable")}
|
|
|
74
74
|
& .crisp-recordstable-td--picker .crisp-multiselect-chips .crisp-recordstable-tag { flex-shrink: 0; max-width: none; }
|
|
75
75
|
& .crisp-recordstable-td--picker .crisp-multiselect-chevron { display: none; }
|
|
76
76
|
& .crisp-recordstable-td--picker .crisp-multiselect-placeholder { color: ${tokens_1.contract.fgMuted}; }
|
|
77
|
+
/* reference picker: a leading 16px avatar per option, plus a trailing
|
|
78
|
+
"Create X" row when the consumer supplies one (#449) -- measured live
|
|
79
|
+
against Attio's own picker (16px circular avatar, 16px plain icon for
|
|
80
|
+
the create row, both sitting in the option's existing 8px gap, no new
|
|
81
|
+
gap value invented). */
|
|
82
|
+
& .crisp-recordstable-refoption { display: flex; align-items: center; gap: ${tokens_1.contract.space["2"]}; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
83
|
+
& .crisp-recordstable-refoption-avatar { flex-shrink: 0; }
|
|
84
|
+
& .crisp-recordstable-refoption--create { color: ${tokens_1.contract.fgMuted}; }
|
|
77
85
|
& .crisp-recordstable-status { display: inline-flex; align-items: center; gap: ${tokens_1.contract.space["1.5"]}; min-width: 0; }
|
|
78
86
|
& .crisp-recordstable-status-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: ${tokens_1.contract.radius.full}; }
|
|
79
87
|
& .crisp-recordstable-cell { display: flex; align-items: center; gap: ${tokens_1.contract.space["2"]}; height: 100%; min-width: 0; }
|
|
@@ -132,7 +140,7 @@ ${(0, tabletoolbar_chrome_1.toolbarChromeBody)("recordstable")}
|
|
|
132
140
|
& .crisp-recordstable-empty { display: flex; align-items: center; justify-content: center; min-height: 320px; padding: ${tokens_1.contract.space["8"]} ${tokens_1.contract.space["4"]}; }
|
|
133
141
|
|
|
134
142
|
/* summary footer — per-column aggregation, sticky to the bottom */
|
|
135
|
-
& .crisp-recordstable-sum { position: sticky; bottom: 0; z-index: 2; height: ${tokens_1.contract.size.tableRow}; padding: 0; border-top: 1px solid ${tokens_1.contract.borderSubtle}; border-inline-end: 1px solid ${tokens_1.contract.borderSubtle}; background: ${tokens_1.contract.bgSurface}; }
|
|
143
|
+
& .crisp-recordstable-sum { position: sticky; bottom: 0; z-index: 2; height: ${tokens_1.contract.size.tableRow}; padding: 0; border-top: 1px solid ${tokens_1.contract.borderSubtle}; border-bottom: 1px solid ${tokens_1.contract.borderSubtle}; border-inline-end: 1px solid ${tokens_1.contract.borderSubtle}; background: ${tokens_1.contract.bgSurface}; }
|
|
136
144
|
& tfoot .crisp-recordstable-col-check, & tfoot .crisp-recordstable-col-entity { position: sticky; bottom: 0; z-index: 3; }
|
|
137
145
|
& .crisp-recordstable-sum:last-child { border-inline-end: none; }
|
|
138
146
|
& .crisp-recordstable-sum-btn { display: flex; align-items: center; justify-content: flex-end; gap: ${tokens_1.contract.space["1.5"]}; width: 100%; height: 100%; margin: 0; padding: 0 ${tokens_1.contract.space["3"]}; border: none; background: none; color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 63%, transparent); font-family: inherit; font-size: ${tokens_1.contract.text.lg}; font-weight: ${tokens_1.contract.weight.medium}; cursor: pointer; white-space: nowrap; overflow: hidden; }
|
|
@@ -7,9 +7,14 @@ const tokens_1 = require("../../tokens");
|
|
|
7
7
|
* `border-radius: ${c.radius.chip}`, 14px/20px at weight 500, and a 1px inset ring in the
|
|
8
8
|
* tone's colour.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
* to be
|
|
12
|
-
*
|
|
10
|
+
* Its own module (not pasted into `recordstable.recipe.ts`) because it used
|
|
11
|
+
* to be shared with `RecordPanel`'s own Details field list too, and the two
|
|
12
|
+
* copies had already started to drift before that sharing existed — adding
|
|
13
|
+
* the measured inset ring meant patching the same rules twice. `RecordPanel`
|
|
14
|
+
* no longer renders a Details list (#448, Attio's own peek doesn't have
|
|
15
|
+
* one), so `RecordsTable` is this module's only consumer now; kept as its
|
|
16
|
+
* own file rather than folded back in, since a second consumer showing up
|
|
17
|
+
* again is exactly how the drift happened the first time.
|
|
13
18
|
*/
|
|
14
19
|
exports.recordTagCss = `& .crisp-recordstable-tag { display: inline-flex; align-items: center; height: ${tokens_1.contract.size.chip}; padding: 0 ${tokens_1.contract.space["1"]}; border-radius: ${tokens_1.contract.radius.chip}; font-size: ${tokens_1.contract.text.lg}; line-height: 20px; font-weight: ${tokens_1.contract.weight.medium}; white-space: nowrap; background: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 6%, transparent); color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 82%, transparent); box-shadow: inset 0 0 0 1px ${tokens_1.contract.borderSubtle}; }
|
|
15
20
|
& .crisp-recordstable-tag[data-tone="brand"] { background: color-mix(in srgb, ${tokens_1.contract.bgBrandSolid} 14%, transparent); color: color-mix(in srgb, ${tokens_1.contract.bgBrandSolid} 82%, ${tokens_1.contract.fgPrimary}); box-shadow: inset 0 0 0 1px color-mix(in srgb, ${tokens_1.contract.bgBrandSolid} 30%, transparent); }
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.richtextRecipe = exports.RichTextEditor = void 0;
|
|
3
|
+
exports.richtextRecipe = exports.RichTextEditor = exports.RICHTEXT_COLOR_TONES = void 0;
|
|
4
4
|
var richtext_1 = require("./richtext");
|
|
5
|
+
Object.defineProperty(exports, "RICHTEXT_COLOR_TONES", { enumerable: true, get: function () { return richtext_1.RICHTEXT_COLOR_TONES; } });
|
|
5
6
|
Object.defineProperty(exports, "RichTextEditor", { enumerable: true, get: function () { return richtext_1.RichTextEditor; } });
|
|
6
7
|
var richtext_recipe_1 = require("./richtext.recipe");
|
|
7
8
|
Object.defineProperty(exports, "richtextRecipe", { enumerable: true, get: function () { return richtext_recipe_1.richtextRecipe; } });
|