@crisp-ui-kit/crisp 0.20.1 → 0.21.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.
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.onboardingRecipe = exports.OnboardingChecklist = void 0;
3
+ exports.onboardingRecipe = exports.onboardingLabels = exports.OnboardingChecklist = void 0;
4
4
  var onboarding_1 = require("./onboarding");
5
5
  Object.defineProperty(exports, "OnboardingChecklist", { enumerable: true, get: function () { return onboarding_1.OnboardingChecklist; } });
6
+ Object.defineProperty(exports, "onboardingLabels", { enumerable: true, get: function () { return onboarding_1.onboardingLabels; } });
6
7
  var onboarding_recipe_1 = require("./onboarding.recipe");
7
8
  Object.defineProperty(exports, "onboardingRecipe", { enumerable: true, get: function () { return onboarding_recipe_1.onboardingRecipe; } });
@@ -1,17 +1,27 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.onboardingLabels = void 0;
3
4
  exports.OnboardingChecklist = OnboardingChecklist;
4
5
  const jsx_runtime_1 = require("react/jsx-runtime");
5
6
  const lucide_react_1 = require("lucide-react");
6
7
  const onboarding_recipe_1 = require("./onboarding.recipe");
8
+ /**
9
+ * The English defaults for the two pieces of copy that are formatters rather
10
+ * than strings. Exported so a consumer can wrap one instead of restating it,
11
+ * and so the strings live in one place rather than inside the signature.
12
+ */
13
+ exports.onboardingLabels = {
14
+ progressText: (done, total) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("b", { children: [done, "/", total] }), " ", "steps completed"] })),
15
+ completedStepLabel: (label) => `${String(label)} — completed`,
16
+ };
7
17
  /**
8
18
  * An onboarding checklist card — measured from Attio's floating "Getting
9
19
  * started" widget. Title + optional menu/minimize, a segmented progress bar,
10
20
  * and step rows (completed rows strike through with a brand check).
11
21
  */
12
- function OnboardingChecklist({ title = "Getting started", steps, encouragement = "Keep it up!", onStepClick, onMenu, onMinimize, className, optionsLabel = "Checklist options", minimizeLabel = "Minimize", progressLabel = "Onboarding progress", }) {
22
+ function OnboardingChecklist({ title = "Getting started", steps, encouragement = "Keep it up!", onStepClick, onMenu, onMinimize, className, optionsLabel = "Checklist options", minimizeLabel = "Minimize", progressLabel = "Onboarding progress", progressText = exports.onboardingLabels.progressText, completedStepLabel = exports.onboardingLabels.completedStepLabel, }) {
13
23
  const total = steps.length;
14
24
  const done = steps.filter((s) => s.done).length;
15
- return ((0, jsx_runtime_1.jsxs)("div", { className: (0, onboarding_recipe_1.onboardingRecipe)({ className }), children: [(0, jsx_runtime_1.jsxs)("div", { className: "onboarding-head", children: [(0, jsx_runtime_1.jsx)("span", { className: "onboarding-title", children: title }), onMenu && ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "onboarding-iconbtn", "aria-label": optionsLabel, onClick: onMenu, children: (0, jsx_runtime_1.jsx)(lucide_react_1.MoreHorizontal, { size: 16, strokeWidth: 1.75 }) })), onMinimize && ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "onboarding-iconbtn", "aria-label": minimizeLabel, onClick: onMinimize, children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: 16, strokeWidth: 1.75 }) }))] }), (0, jsx_runtime_1.jsxs)("span", { className: "onboarding-sub", children: [(0, jsx_runtime_1.jsxs)("b", { children: [done, "/", total] }), " ", "steps completed", encouragement ? (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [" \u00B7 ", encouragement] }) : null] }), (0, jsx_runtime_1.jsx)("div", { className: "onboarding-progress", role: "progressbar", "aria-valuenow": done, "aria-valuemin": 0, "aria-valuemax": total, "aria-label": progressLabel, children: Array.from({ length: total }, (_, i) => ((0, jsx_runtime_1.jsx)("span", { className: "onboarding-seg", "data-done": i < done ? "" : undefined }, i))) }), (0, jsx_runtime_1.jsx)("div", { className: "onboarding-steps", children: steps.map((s) => ((0, jsx_runtime_1.jsxs)("button", { type: "button", className: "onboarding-step", "data-done": s.done ? "" : undefined, disabled: s.done, onClick: s.done ? undefined : () => onStepClick?.(s.id), children: [(0, jsx_runtime_1.jsx)("span", { className: "onboarding-step-icon", children: s.icon }), (0, jsx_runtime_1.jsx)("span", { className: "onboarding-step-label", children: s.label }), (0, jsx_runtime_1.jsx)("span", { className: "onboarding-step-check", children: s.done && (0, jsx_runtime_1.jsx)(lucide_react_1.Check, { size: 12, strokeWidth: 3 }) })] }, s.id))) })] }));
25
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, onboarding_recipe_1.onboardingRecipe)({ className }), children: [(0, jsx_runtime_1.jsxs)("div", { className: "onboarding-head", children: [(0, jsx_runtime_1.jsx)("span", { className: "onboarding-title", children: title }), onMenu && ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "onboarding-iconbtn", "aria-label": optionsLabel, onClick: onMenu, children: (0, jsx_runtime_1.jsx)(lucide_react_1.MoreHorizontal, { size: 16, strokeWidth: 1.75 }) })), onMinimize && ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "onboarding-iconbtn", "aria-label": minimizeLabel, onClick: onMinimize, children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: 16, strokeWidth: 1.75 }) }))] }), (0, jsx_runtime_1.jsxs)("span", { className: "onboarding-sub", children: [progressText(done, total), encouragement ? (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [" \u00B7 ", encouragement] }) : null] }), (0, jsx_runtime_1.jsx)("div", { className: "onboarding-progress", role: "progressbar", "aria-valuenow": done, "aria-valuemin": 0, "aria-valuemax": total, "aria-label": progressLabel, children: Array.from({ length: total }, (_, i) => ((0, jsx_runtime_1.jsx)("span", { className: "onboarding-seg", "data-done": i < done ? "" : undefined }, i))) }), (0, jsx_runtime_1.jsx)("div", { className: "onboarding-steps", children: steps.map((s) => ((0, jsx_runtime_1.jsxs)("button", { type: "button", className: "onboarding-step", "data-done": s.done ? "" : undefined, "aria-label": s.done ? completedStepLabel(s.label) : undefined, disabled: s.done, onClick: s.done ? undefined : () => onStepClick?.(s.id), children: [(0, jsx_runtime_1.jsx)("span", { className: "onboarding-step-icon", children: s.icon }), (0, jsx_runtime_1.jsx)("span", { className: "onboarding-step-label", children: s.label }), (0, jsx_runtime_1.jsx)("span", { className: "onboarding-step-check", children: s.done && (0, jsx_runtime_1.jsx)(lucide_react_1.Check, { size: 12, strokeWidth: 3 }) })] }, s.id))) })] }));
16
26
  }
17
27
  OnboardingChecklist.displayName = "OnboardingChecklist";
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.recordpageRecipe = exports.RecordPage = void 0;
3
+ exports.recordpageRecipe = exports.recordPageLabels = exports.RecordPage = void 0;
4
4
  var recordpage_1 = require("./recordpage");
5
5
  Object.defineProperty(exports, "RecordPage", { enumerable: true, get: function () { return recordpage_1.RecordPage; } });
6
+ Object.defineProperty(exports, "recordPageLabels", { enumerable: true, get: function () { return recordpage_1.recordPageLabels; } });
6
7
  var recordpage_recipe_1 = require("./recordpage.recipe");
7
8
  Object.defineProperty(exports, "recordpageRecipe", { enumerable: true, get: function () { return recordpage_recipe_1.recordpageRecipe; } });
@@ -119,6 +119,8 @@ exports.recordPageLabels = {
119
119
  },
120
120
  domainSetTo: (value) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Domain set to ", (0, jsx_runtime_1.jsx)("b", { children: value })] })),
121
121
  taggedCategories: (count) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Tagged ", (0, jsx_runtime_1.jsx)("b", { children: count }), " categories"] })),
122
+ recordCreated: (name) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("b", { children: name }), " record was created"] })),
123
+ noEmailsWith: (name) => (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["No emails logged with ", name, " yet."] }),
122
124
  };
123
125
  function TagsValue({ values }) {
124
126
  const [expanded, setExpanded] = React.useState(false);
@@ -367,13 +369,13 @@ function RecordPage({ record, columns, collection = "Records", labels, onBack, o
367
369
  : null,
368
370
  {
369
371
  id: "created",
370
- text: ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("b", { children: name }), " record was created"] })),
372
+ text: t.recordCreated(name),
371
373
  time: "1 day ago",
372
374
  },
373
375
  ].filter(Boolean);
374
376
  const shownActivity = showAllActivity ? activity : activity.slice(0, 2);
375
377
  const activityFeed = ((0, jsx_runtime_1.jsxs)("section", { children: [(0, jsx_runtime_1.jsx)(SectionHead, { title: t.tabs.activity, action: activity.length > 2 ? ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "recordpage-viewall recordpage-viewall--inline", onClick: () => setShowAllActivity((s) => !s), children: showAllActivity ? t.showLess : t.viewAll })) : undefined }), (0, jsx_runtime_1.jsx)("div", { className: "recordpage-feed", children: shownActivity.map((a) => ((0, jsx_runtime_1.jsxs)("div", { className: "recordpage-feed-item", children: [(0, jsx_runtime_1.jsx)("span", { className: "recordpage-feed-dot", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Activity, { size: 13, strokeWidth: 2 }) }), (0, jsx_runtime_1.jsxs)("div", { className: "recordpage-feed-body", children: [a.text, (0, jsx_runtime_1.jsx)("div", { className: "recordpage-feed-time", children: a.time })] })] }, a.id))) })] }));
376
- const emailsEmpty = ((0, jsx_runtime_1.jsxs)(EmptyCard, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Inbox, { size: 22, strokeWidth: 1.5 }), children: ["No emails logged with ", name, " yet."] }));
378
+ const emailsEmpty = ((0, jsx_runtime_1.jsx)(EmptyCard, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Inbox, { size: 22, strokeWidth: 1.5 }), children: t.noEmailsWith(name) }));
377
379
  const panel = (active) => {
378
380
  switch (active) {
379
381
  case "overview":
@@ -52,6 +52,7 @@ const menu_1 = require("../../components/menu");
52
52
  const multiselect_1 = require("../../components/multiselect");
53
53
  const select_1 = require("../../components/select");
54
54
  const switch_1 = require("../../components/switch");
55
+ const core_1 = require("../../core");
55
56
  const company_logos_1 = require("./company-logos");
56
57
  const recordstable_recipe_1 = require("./recordstable.recipe");
57
58
  const EDITABLE = new Set(["text", "number", "url", "currency"]);
@@ -897,7 +898,11 @@ function RecordsTable({ labels, columns: columnsProp = exports.defaultColumns, r
897
898
  setOpenMenu(null);
898
899
  };
899
900
  // column resize via pointer drag on the header edge
900
- const resizeCol = (key, startX, startW) => {
901
+ const resizeCol = (key, startX, startW, grip) => {
902
+ // A table's columns reverse under RTL — measured — so the grip sits on the
903
+ // column's leading edge there and a rightward pull must SHRINK it. The
904
+ // anchor is `inset-inline-end`; this is the other half (#214).
905
+ const dir = (0, core_1.isRtlElement)(grip) ? -1 : 1;
901
906
  // guard the whole document during the drag: kill text selection and force a
902
907
  // resize cursor so the gesture doesn't select cells or flicker (was buggy)
903
908
  const prevSelect = document.body.style.userSelect;
@@ -905,7 +910,7 @@ function RecordsTable({ labels, columns: columnsProp = exports.defaultColumns, r
905
910
  document.body.style.userSelect = "none";
906
911
  document.body.style.cursor = "col-resize";
907
912
  const onMove = (e) => {
908
- const w = Math.round(Math.max(72, startW + (e.clientX - startX)));
913
+ const w = Math.round(Math.max(72, startW + dir * (e.clientX - startX)));
909
914
  setCols((prev) => prev.map((c) => (c.key === key ? { ...c, width: w } : c)));
910
915
  };
911
916
  const onUp = () => {
@@ -995,7 +1000,7 @@ function RecordsTable({ labels, columns: columnsProp = exports.defaultColumns, r
995
1000
  e.stopPropagation();
996
1001
  const th = e.currentTarget
997
1002
  .parentElement;
998
- resizeCol(col.key, e.clientX, th ? th.getBoundingClientRect().width : 180);
1003
+ resizeCol(col.key, e.clientX, th ? th.getBoundingClientRect().width : 180, e.currentTarget);
999
1004
  }, onClick: (e) => e.stopPropagation() })] }, col.key));
1000
1005
  }), (0, jsx_runtime_1.jsx)("th", { className: "recordstable-th recordstable-addcol", children: allowAddColumn && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: addColumn, "aria-label": t.addColumn, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 15, strokeWidth: 1.75 }) })) })] }) }), (0, jsx_runtime_1.jsx)("tbody", { children: visibleRows.map((row) => ((0, jsx_runtime_1.jsxs)("tr", { "data-selected": selected.has(row.id) ? "" : undefined, onContextMenu: (e) => {
1001
1006
  e.preventDefault();
@@ -46,8 +46,8 @@ ${(0, tabletoolbar_chrome_1.toolbarChromeBody)("recordstable")}
46
46
  & .recordstable-th[data-sorted="desc"] .recordstable-sort svg { transform: rotate(180deg); }
47
47
 
48
48
  /* column resize handle */
49
- & .recordstable-resize { position: absolute; top: 0; right: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
50
- & .recordstable-resize::after { content: ""; position: absolute; top: 0; left: 3px; width: 2px; height: 100%; background: ${tokens_1.contract.bgBrandSolid}; opacity: 0; transition: opacity .12s; }
49
+ & .recordstable-resize { position: absolute; top: 0; inset-inline-end: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
50
+ & .recordstable-resize::after { content: ""; position: absolute; top: 0; inset-inline-start: 3px; width: 2px; height: 100%; background: ${tokens_1.contract.bgBrandSolid}; opacity: 0; transition: opacity .12s; }
51
51
  & .recordstable-resize:hover::after, & .recordstable-resize[data-resizing]::after { opacity: 1; }
52
52
 
53
53
  /* add-column header */
@@ -1,2 +1,2 @@
1
- export { OnboardingChecklist, } from "./onboarding.js";
1
+ export { OnboardingChecklist, onboardingLabels, } from "./onboarding.js";
2
2
  export { onboardingRecipe } from "./onboarding.recipe.js";
@@ -1,14 +1,23 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Check, ChevronDown, MoreHorizontal } from "lucide-react";
3
3
  import { onboardingRecipe } from "./onboarding.recipe.js";
4
+ /**
5
+ * The English defaults for the two pieces of copy that are formatters rather
6
+ * than strings. Exported so a consumer can wrap one instead of restating it,
7
+ * and so the strings live in one place rather than inside the signature.
8
+ */
9
+ export const onboardingLabels = {
10
+ progressText: (done, total) => (_jsxs(_Fragment, { children: [_jsxs("b", { children: [done, "/", total] }), " ", "steps completed"] })),
11
+ completedStepLabel: (label) => `${String(label)} — completed`,
12
+ };
4
13
  /**
5
14
  * An onboarding checklist card — measured from Attio's floating "Getting
6
15
  * started" widget. Title + optional menu/minimize, a segmented progress bar,
7
16
  * and step rows (completed rows strike through with a brand check).
8
17
  */
9
- export function OnboardingChecklist({ title = "Getting started", steps, encouragement = "Keep it up!", onStepClick, onMenu, onMinimize, className, optionsLabel = "Checklist options", minimizeLabel = "Minimize", progressLabel = "Onboarding progress", }) {
18
+ export function OnboardingChecklist({ title = "Getting started", steps, encouragement = "Keep it up!", onStepClick, onMenu, onMinimize, className, optionsLabel = "Checklist options", minimizeLabel = "Minimize", progressLabel = "Onboarding progress", progressText = onboardingLabels.progressText, completedStepLabel = onboardingLabels.completedStepLabel, }) {
10
19
  const total = steps.length;
11
20
  const done = steps.filter((s) => s.done).length;
12
- return (_jsxs("div", { className: onboardingRecipe({ className }), children: [_jsxs("div", { className: "onboarding-head", children: [_jsx("span", { className: "onboarding-title", children: title }), onMenu && (_jsx("button", { type: "button", className: "onboarding-iconbtn", "aria-label": optionsLabel, onClick: onMenu, children: _jsx(MoreHorizontal, { size: 16, strokeWidth: 1.75 }) })), onMinimize && (_jsx("button", { type: "button", className: "onboarding-iconbtn", "aria-label": minimizeLabel, onClick: onMinimize, children: _jsx(ChevronDown, { size: 16, strokeWidth: 1.75 }) }))] }), _jsxs("span", { className: "onboarding-sub", children: [_jsxs("b", { children: [done, "/", total] }), " ", "steps completed", encouragement ? _jsxs(_Fragment, { children: [" \u00B7 ", encouragement] }) : null] }), _jsx("div", { className: "onboarding-progress", role: "progressbar", "aria-valuenow": done, "aria-valuemin": 0, "aria-valuemax": total, "aria-label": progressLabel, children: Array.from({ length: total }, (_, i) => (_jsx("span", { className: "onboarding-seg", "data-done": i < done ? "" : undefined }, i))) }), _jsx("div", { className: "onboarding-steps", children: steps.map((s) => (_jsxs("button", { type: "button", className: "onboarding-step", "data-done": s.done ? "" : undefined, disabled: s.done, onClick: s.done ? undefined : () => onStepClick?.(s.id), children: [_jsx("span", { className: "onboarding-step-icon", children: s.icon }), _jsx("span", { className: "onboarding-step-label", children: s.label }), _jsx("span", { className: "onboarding-step-check", children: s.done && _jsx(Check, { size: 12, strokeWidth: 3 }) })] }, s.id))) })] }));
21
+ return (_jsxs("div", { className: onboardingRecipe({ className }), children: [_jsxs("div", { className: "onboarding-head", children: [_jsx("span", { className: "onboarding-title", children: title }), onMenu && (_jsx("button", { type: "button", className: "onboarding-iconbtn", "aria-label": optionsLabel, onClick: onMenu, children: _jsx(MoreHorizontal, { size: 16, strokeWidth: 1.75 }) })), onMinimize && (_jsx("button", { type: "button", className: "onboarding-iconbtn", "aria-label": minimizeLabel, onClick: onMinimize, children: _jsx(ChevronDown, { size: 16, strokeWidth: 1.75 }) }))] }), _jsxs("span", { className: "onboarding-sub", children: [progressText(done, total), encouragement ? _jsxs(_Fragment, { children: [" \u00B7 ", encouragement] }) : null] }), _jsx("div", { className: "onboarding-progress", role: "progressbar", "aria-valuenow": done, "aria-valuemin": 0, "aria-valuemax": total, "aria-label": progressLabel, children: Array.from({ length: total }, (_, i) => (_jsx("span", { className: "onboarding-seg", "data-done": i < done ? "" : undefined }, i))) }), _jsx("div", { className: "onboarding-steps", children: steps.map((s) => (_jsxs("button", { type: "button", className: "onboarding-step", "data-done": s.done ? "" : undefined, "aria-label": s.done ? completedStepLabel(s.label) : undefined, disabled: s.done, onClick: s.done ? undefined : () => onStepClick?.(s.id), children: [_jsx("span", { className: "onboarding-step-icon", children: s.icon }), _jsx("span", { className: "onboarding-step-label", children: s.label }), _jsx("span", { className: "onboarding-step-check", children: s.done && _jsx(Check, { size: 12, strokeWidth: 3 }) })] }, s.id))) })] }));
13
22
  }
14
23
  OnboardingChecklist.displayName = "OnboardingChecklist";
@@ -1,2 +1,2 @@
1
- export { RecordPage } from "./recordpage.js";
1
+ export { RecordPage, recordPageLabels, } from "./recordpage.js";
2
2
  export { recordpageRecipe } from "./recordpage.recipe.js";
@@ -82,6 +82,8 @@ export const recordPageLabels = {
82
82
  },
83
83
  domainSetTo: (value) => (_jsxs(_Fragment, { children: ["Domain set to ", _jsx("b", { children: value })] })),
84
84
  taggedCategories: (count) => (_jsxs(_Fragment, { children: ["Tagged ", _jsx("b", { children: count }), " categories"] })),
85
+ recordCreated: (name) => (_jsxs(_Fragment, { children: [_jsx("b", { children: name }), " record was created"] })),
86
+ noEmailsWith: (name) => _jsxs(_Fragment, { children: ["No emails logged with ", name, " yet."] }),
85
87
  };
86
88
  function TagsValue({ values }) {
87
89
  const [expanded, setExpanded] = React.useState(false);
@@ -330,13 +332,13 @@ export function RecordPage({ record, columns, collection = "Records", labels, on
330
332
  : null,
331
333
  {
332
334
  id: "created",
333
- text: (_jsxs(_Fragment, { children: [_jsx("b", { children: name }), " record was created"] })),
335
+ text: t.recordCreated(name),
334
336
  time: "1 day ago",
335
337
  },
336
338
  ].filter(Boolean);
337
339
  const shownActivity = showAllActivity ? activity : activity.slice(0, 2);
338
340
  const activityFeed = (_jsxs("section", { children: [_jsx(SectionHead, { title: t.tabs.activity, action: activity.length > 2 ? (_jsx("button", { type: "button", className: "recordpage-viewall recordpage-viewall--inline", onClick: () => setShowAllActivity((s) => !s), children: showAllActivity ? t.showLess : t.viewAll })) : undefined }), _jsx("div", { className: "recordpage-feed", children: shownActivity.map((a) => (_jsxs("div", { className: "recordpage-feed-item", children: [_jsx("span", { className: "recordpage-feed-dot", children: _jsx(ActivityIcon, { size: 13, strokeWidth: 2 }) }), _jsxs("div", { className: "recordpage-feed-body", children: [a.text, _jsx("div", { className: "recordpage-feed-time", children: a.time })] })] }, a.id))) })] }));
339
- const emailsEmpty = (_jsxs(EmptyCard, { icon: _jsx(Inbox, { size: 22, strokeWidth: 1.5 }), children: ["No emails logged with ", name, " yet."] }));
341
+ const emailsEmpty = (_jsx(EmptyCard, { icon: _jsx(Inbox, { size: 22, strokeWidth: 1.5 }), children: t.noEmailsWith(name) }));
340
342
  const panel = (active) => {
341
343
  switch (active) {
342
344
  case "overview":
@@ -14,6 +14,7 @@ import { Menu, MenuItem, useMenuKeyboard } from "../../components/menu/index.js"
14
14
  import { MultiSelect } from "../../components/multiselect/index.js";
15
15
  import { Select } from "../../components/select/index.js";
16
16
  import { Switch } from "../../components/switch/index.js";
17
+ import { isRtlElement } from "../../core/index.js";
17
18
  import { companyLogos } from "./company-logos.js";
18
19
  import { recordstableRecipe } from "./recordstable.recipe.js";
19
20
  const EDITABLE = new Set(["text", "number", "url", "currency"]);
@@ -859,7 +860,11 @@ export function RecordsTable({ labels, columns: columnsProp = defaultColumns, ro
859
860
  setOpenMenu(null);
860
861
  };
861
862
  // column resize via pointer drag on the header edge
862
- const resizeCol = (key, startX, startW) => {
863
+ const resizeCol = (key, startX, startW, grip) => {
864
+ // A table's columns reverse under RTL — measured — so the grip sits on the
865
+ // column's leading edge there and a rightward pull must SHRINK it. The
866
+ // anchor is `inset-inline-end`; this is the other half (#214).
867
+ const dir = isRtlElement(grip) ? -1 : 1;
863
868
  // guard the whole document during the drag: kill text selection and force a
864
869
  // resize cursor so the gesture doesn't select cells or flicker (was buggy)
865
870
  const prevSelect = document.body.style.userSelect;
@@ -867,7 +872,7 @@ export function RecordsTable({ labels, columns: columnsProp = defaultColumns, ro
867
872
  document.body.style.userSelect = "none";
868
873
  document.body.style.cursor = "col-resize";
869
874
  const onMove = (e) => {
870
- const w = Math.round(Math.max(72, startW + (e.clientX - startX)));
875
+ const w = Math.round(Math.max(72, startW + dir * (e.clientX - startX)));
871
876
  setCols((prev) => prev.map((c) => (c.key === key ? { ...c, width: w } : c)));
872
877
  };
873
878
  const onUp = () => {
@@ -957,7 +962,7 @@ export function RecordsTable({ labels, columns: columnsProp = defaultColumns, ro
957
962
  e.stopPropagation();
958
963
  const th = e.currentTarget
959
964
  .parentElement;
960
- resizeCol(col.key, e.clientX, th ? th.getBoundingClientRect().width : 180);
965
+ resizeCol(col.key, e.clientX, th ? th.getBoundingClientRect().width : 180, e.currentTarget);
961
966
  }, onClick: (e) => e.stopPropagation() })] }, col.key));
962
967
  }), _jsx("th", { className: "recordstable-th recordstable-addcol", children: allowAddColumn && (_jsx("button", { type: "button", onClick: addColumn, "aria-label": t.addColumn, children: _jsx(Plus, { size: 15, strokeWidth: 1.75 }) })) })] }) }), _jsx("tbody", { children: visibleRows.map((row) => (_jsxs("tr", { "data-selected": selected.has(row.id) ? "" : undefined, onContextMenu: (e) => {
963
968
  e.preventDefault();
@@ -43,8 +43,8 @@ ${toolbarChromeBody("recordstable")}
43
43
  & .recordstable-th[data-sorted="desc"] .recordstable-sort svg { transform: rotate(180deg); }
44
44
 
45
45
  /* column resize handle */
46
- & .recordstable-resize { position: absolute; top: 0; right: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
47
- & .recordstable-resize::after { content: ""; position: absolute; top: 0; left: 3px; width: 2px; height: 100%; background: ${c.bgBrandSolid}; opacity: 0; transition: opacity .12s; }
46
+ & .recordstable-resize { position: absolute; top: 0; inset-inline-end: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
47
+ & .recordstable-resize::after { content: ""; position: absolute; top: 0; inset-inline-start: 3px; width: 2px; height: 100%; background: ${c.bgBrandSolid}; opacity: 0; transition: opacity .12s; }
48
48
  & .recordstable-resize:hover::after, & .recordstable-resize[data-resizing]::after { opacity: 1; }
49
49
 
50
50
  /* add-column header */
@@ -91,8 +91,8 @@
91
91
  & .recordstable-th[data-sorted="desc"] .recordstable-sort svg { transform: rotate(180deg); }
92
92
 
93
93
  /* column resize handle */
94
- & .recordstable-resize { position: absolute; top: 0; right: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
95
- & .recordstable-resize::after { content: ""; position: absolute; top: 0; left: 3px; width: 2px; height: 100%; background: var(--bg-brand-solid); opacity: 0; transition: opacity .12s; }
94
+ & .recordstable-resize { position: absolute; top: 0; inset-inline-end: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
95
+ & .recordstable-resize::after { content: ""; position: absolute; top: 0; inset-inline-start: 3px; width: 2px; height: 100%; background: var(--bg-brand-solid); opacity: 0; transition: opacity .12s; }
96
96
  & .recordstable-resize:hover::after, & .recordstable-resize[data-resizing]::after { opacity: 1; }
97
97
 
98
98
  /* add-column header */
package/dist/styles.css CHANGED
@@ -2483,8 +2483,8 @@
2483
2483
  & .recordstable-th[data-sorted="desc"] .recordstable-sort svg { transform: rotate(180deg); }
2484
2484
 
2485
2485
  /* column resize handle */
2486
- & .recordstable-resize { position: absolute; top: 0; right: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
2487
- & .recordstable-resize::after { content: ""; position: absolute; top: 0; left: 3px; width: 2px; height: 100%; background: var(--bg-brand-solid); opacity: 0; transition: opacity .12s; }
2486
+ & .recordstable-resize { position: absolute; top: 0; inset-inline-end: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
2487
+ & .recordstable-resize::after { content: ""; position: absolute; top: 0; inset-inline-start: 3px; width: 2px; height: 100%; background: var(--bg-brand-solid); opacity: 0; transition: opacity .12s; }
2488
2488
  & .recordstable-resize:hover::after, & .recordstable-resize[data-resizing]::after { opacity: 1; }
2489
2489
 
2490
2490
  /* add-column header */
@@ -1,2 +1,2 @@
1
- export { OnboardingChecklist, type OnboardingChecklistProps, type OnboardingStep, } from "./onboarding";
1
+ export { OnboardingChecklist, type OnboardingChecklistProps, type OnboardingStep, onboardingLabels, } from "./onboarding";
2
2
  export { onboardingRecipe } from "./onboarding.recipe";
@@ -14,6 +14,18 @@ export type OnboardingChecklistProps = {
14
14
  minimizeLabel?: string;
15
15
  /** Accessible name for the progress bar. */
16
16
  progressLabel?: string;
17
+ /**
18
+ * The "N/total steps completed" line. A formatter, not a string: the count
19
+ * moves within the sentence between languages, so a template with holes
20
+ * cannot be translated (#216).
21
+ */
22
+ progressText?: (done: number, total: number) => React.ReactNode;
23
+ /**
24
+ * Accessible name for a completed step. Without one, a done step announces
25
+ * as "…, button, dimmed" and the strikethrough and check glyph — its only
26
+ * other signals — are invisible to a screen reader.
27
+ */
28
+ completedStepLabel?: (label: React.ReactNode) => string;
17
29
  title?: React.ReactNode;
18
30
  steps: OnboardingStep[];
19
31
  /** Subtitle after "N/total steps completed" (default "Keep it up!"). */
@@ -26,12 +38,21 @@ export type OnboardingChecklistProps = {
26
38
  onMinimize?: () => void;
27
39
  className?: string;
28
40
  };
41
+ /**
42
+ * The English defaults for the two pieces of copy that are formatters rather
43
+ * than strings. Exported so a consumer can wrap one instead of restating it,
44
+ * and so the strings live in one place rather than inside the signature.
45
+ */
46
+ export declare const onboardingLabels: {
47
+ progressText: (done: number, total: number) => React.ReactNode;
48
+ completedStepLabel: (label: React.ReactNode) => string;
49
+ };
29
50
  /**
30
51
  * An onboarding checklist card — measured from Attio's floating "Getting
31
52
  * started" widget. Title + optional menu/minimize, a segmented progress bar,
32
53
  * and step rows (completed rows strike through with a brand check).
33
54
  */
34
- export declare function OnboardingChecklist({ title, steps, encouragement, onStepClick, onMenu, onMinimize, className, optionsLabel, minimizeLabel, progressLabel, }: OnboardingChecklistProps): React.JSX.Element;
55
+ export declare function OnboardingChecklist({ title, steps, encouragement, onStepClick, onMenu, onMinimize, className, optionsLabel, minimizeLabel, progressLabel, progressText, completedStepLabel, }: OnboardingChecklistProps): React.JSX.Element;
35
56
  export declare namespace OnboardingChecklist {
36
57
  var displayName: string;
37
58
  }
@@ -1,2 +1,2 @@
1
- export { RecordPage, type RecordPageProps } from "./recordpage";
1
+ export { RecordPage, type RecordPageLabels, type RecordPageLabelsInput, type RecordPageProps, recordPageLabels, } from "./recordpage";
2
2
  export { recordpageRecipe } from "./recordpage.recipe";
@@ -77,6 +77,10 @@ export type RecordPageLabels = {
77
77
  domainSetTo: (value: React.ReactNode) => React.ReactNode;
78
78
  /** Activity line for added categories, given how many. */
79
79
  taggedCategories: (count: number) => React.ReactNode;
80
+ /** Activity line for the record's creation, given its name. */
81
+ recordCreated: (name: React.ReactNode) => React.ReactNode;
82
+ /** Empty state on the Emails tab, given the record's name. */
83
+ noEmailsWith: (name: React.ReactNode) => React.ReactNode;
80
84
  };
81
85
  export declare const recordPageLabels: RecordPageLabels;
82
86
  /** Partial override of any chrome string; the keyed maps nest. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crisp-ui-kit/crisp",
3
- "version": "0.20.1",
3
+ "version": "0.21.0",
4
4
  "description": "A lean React design system, measured pixel-for-pixel from Attio.",
5
5
  "license": "MIT",
6
6
  "type": "module",