@crisp-ui-kit/crisp 0.57.2 → 0.57.4

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.
Files changed (200) hide show
  1. package/dist/assigneepicker.css +13 -0
  2. package/dist/assigneepicker.d.ts +7 -0
  3. package/dist/assigneepicker.layered.css +15 -0
  4. package/dist/button.css +3 -0
  5. package/dist/button.d.ts +2 -2
  6. package/dist/button.layered.css +3 -0
  7. package/dist/chip.css +1 -1
  8. package/dist/chip.layered.css +1 -1
  9. package/dist/cjs/components/breadcrumb/breadcrumb.js +1 -1
  10. package/dist/cjs/components/button/button.recipe.js +33 -0
  11. package/dist/cjs/components/chip/chip.recipe.js +3 -1
  12. package/dist/cjs/components/datatable/datatable.js +6 -3
  13. package/dist/cjs/components/datatable/datatable.recipe.js +45 -6
  14. package/dist/cjs/components/datepickerfield/datepickerfield.js +2 -2
  15. package/dist/cjs/components/datepickerfield/datepickerfield.recipe.js +16 -3
  16. package/dist/cjs/components/menu/menu.js +65 -9
  17. package/dist/cjs/components/multiselect/multiselect.js +3 -0
  18. package/dist/cjs/components/multiselect/multiselect.recipe.js +18 -0
  19. package/dist/cjs/components/select/select.js +2 -2
  20. package/dist/cjs/components/select/select.recipe.js +19 -0
  21. package/dist/cjs/components/table/table.recipe.js +7 -1
  22. package/dist/cjs/core/floating-portal.js +7 -4
  23. package/dist/cjs/core/index.js +2 -1
  24. package/dist/cjs/core/place-floating.js +38 -0
  25. package/dist/cjs/index.js +8 -0
  26. package/dist/cjs/product/assigneepicker/assigneepicker.js +127 -0
  27. package/dist/cjs/product/assigneepicker/assigneepicker.recipe.js +36 -0
  28. package/dist/cjs/product/assigneepicker/index.js +7 -0
  29. package/dist/cjs/product/inbox/inbox.js +11 -3
  30. package/dist/cjs/product/notesgallery/index.js +7 -0
  31. package/dist/cjs/product/notesgallery/notesgallery.js +80 -0
  32. package/dist/cjs/product/notesgallery/notesgallery.recipe.js +46 -0
  33. package/dist/cjs/product/objectpagemenu/index.js +17 -0
  34. package/dist/cjs/product/objectpagemenu/objectpagemenu.js +26 -0
  35. package/dist/cjs/product/objectpagemenu/objectpagemenu.recipe.js +30 -0
  36. package/dist/cjs/product/objectsettings/objectsettings.js +107 -14
  37. package/dist/cjs/product/recordpage/index.js +2 -1
  38. package/dist/cjs/product/recordpage/recordpage.js +112 -7
  39. package/dist/cjs/product/recordpage/recordpage.recipe.js +63 -0
  40. package/dist/cjs/product/recordpicker/index.js +7 -0
  41. package/dist/cjs/product/recordpicker/recordpicker.js +100 -0
  42. package/dist/cjs/product/recordpicker/recordpicker.recipe.js +36 -0
  43. package/dist/cjs/product/savedviews/index.js +2 -1
  44. package/dist/cjs/product/savedviews/savedviews.js +22 -0
  45. package/dist/cjs/product/savedviews/savedviews.recipe.js +47 -0
  46. package/dist/cjs/product/share/index.js +7 -0
  47. package/dist/cjs/product/share/share.js +179 -0
  48. package/dist/cjs/product/share/share.recipe.js +114 -0
  49. package/dist/cjs/product/shortcutssheet/index.js +17 -0
  50. package/dist/cjs/product/shortcutssheet/shortcutssheet.js +125 -0
  51. package/dist/cjs/product/shortcutssheet/shortcutssheet.recipe.js +50 -0
  52. package/dist/cjs/product/taskeditpopover/index.js +7 -0
  53. package/dist/cjs/product/taskeditpopover/taskeditpopover.js +159 -0
  54. package/dist/cjs/product/taskeditpopover/taskeditpopover.recipe.js +68 -0
  55. package/dist/cjs/product/workspaceswitchermenu/index.js +17 -0
  56. package/dist/cjs/product/workspaceswitchermenu/workspaceswitchermenu.js +38 -0
  57. package/dist/cjs/product/workspaceswitchermenu/workspaceswitchermenu.recipe.js +34 -0
  58. package/dist/cjs/tokens/palette.js +27 -0
  59. package/dist/cjs/tokens/semantic.js +20 -0
  60. package/dist/datatable.css +50 -11
  61. package/dist/datatable.layered.css +50 -11
  62. package/dist/datepickerfield.css +8 -2
  63. package/dist/datepickerfield.d.ts +2 -2
  64. package/dist/datepickerfield.layered.css +8 -2
  65. package/dist/esm/components/breadcrumb/breadcrumb.js +1 -1
  66. package/dist/esm/components/button/button.recipe.js +33 -0
  67. package/dist/esm/components/chip/chip.recipe.js +3 -1
  68. package/dist/esm/components/datatable/datatable.js +6 -3
  69. package/dist/esm/components/datatable/datatable.recipe.js +45 -6
  70. package/dist/esm/components/datepickerfield/datepickerfield.js +2 -2
  71. package/dist/esm/components/datepickerfield/datepickerfield.recipe.js +16 -3
  72. package/dist/esm/components/menu/menu.js +64 -8
  73. package/dist/esm/components/multiselect/multiselect.js +3 -0
  74. package/dist/esm/components/multiselect/multiselect.recipe.js +18 -0
  75. package/dist/esm/components/select/select.js +2 -2
  76. package/dist/esm/components/select/select.recipe.js +19 -0
  77. package/dist/esm/components/table/table.recipe.js +7 -1
  78. package/dist/esm/core/floating-portal.js +7 -4
  79. package/dist/esm/core/index.js +1 -1
  80. package/dist/esm/core/place-floating.js +37 -0
  81. package/dist/esm/index.js +8 -0
  82. package/dist/esm/product/assigneepicker/assigneepicker.js +91 -0
  83. package/dist/esm/product/assigneepicker/assigneepicker.recipe.js +33 -0
  84. package/dist/esm/product/assigneepicker/index.js +2 -0
  85. package/dist/esm/product/inbox/inbox.js +11 -3
  86. package/dist/esm/product/notesgallery/index.js +2 -0
  87. package/dist/esm/product/notesgallery/notesgallery.js +44 -0
  88. package/dist/esm/product/notesgallery/notesgallery.recipe.js +43 -0
  89. package/dist/esm/product/objectpagemenu/index.js +1 -0
  90. package/dist/esm/product/objectpagemenu/objectpagemenu.js +23 -0
  91. package/dist/esm/product/objectpagemenu/objectpagemenu.recipe.js +27 -0
  92. package/dist/esm/product/objectsettings/objectsettings.js +106 -13
  93. package/dist/esm/product/recordpage/index.js +1 -1
  94. package/dist/esm/product/recordpage/recordpage.js +112 -8
  95. package/dist/esm/product/recordpage/recordpage.recipe.js +63 -0
  96. package/dist/esm/product/recordpicker/index.js +2 -0
  97. package/dist/esm/product/recordpicker/recordpicker.js +64 -0
  98. package/dist/esm/product/recordpicker/recordpicker.recipe.js +33 -0
  99. package/dist/esm/product/savedviews/index.js +1 -1
  100. package/dist/esm/product/savedviews/savedviews.js +22 -1
  101. package/dist/esm/product/savedviews/savedviews.recipe.js +47 -0
  102. package/dist/esm/product/share/index.js +2 -0
  103. package/dist/esm/product/share/share.js +143 -0
  104. package/dist/esm/product/share/share.recipe.js +111 -0
  105. package/dist/esm/product/shortcutssheet/index.js +1 -0
  106. package/dist/esm/product/shortcutssheet/shortcutssheet.js +88 -0
  107. package/dist/esm/product/shortcutssheet/shortcutssheet.recipe.js +47 -0
  108. package/dist/esm/product/taskeditpopover/index.js +2 -0
  109. package/dist/esm/product/taskeditpopover/taskeditpopover.js +123 -0
  110. package/dist/esm/product/taskeditpopover/taskeditpopover.recipe.js +65 -0
  111. package/dist/esm/product/workspaceswitchermenu/index.js +1 -0
  112. package/dist/esm/product/workspaceswitchermenu/workspaceswitchermenu.js +35 -0
  113. package/dist/esm/product/workspaceswitchermenu/workspaceswitchermenu.recipe.js +31 -0
  114. package/dist/esm/tokens/palette.js +27 -0
  115. package/dist/esm/tokens/semantic.js +20 -0
  116. package/dist/multiselect.css +18 -0
  117. package/dist/multiselect.layered.css +18 -0
  118. package/dist/native/tokens.d.ts +1 -1
  119. package/dist/native/tokens.js +56 -4
  120. package/dist/notesgallery.css +15 -0
  121. package/dist/notesgallery.d.ts +7 -0
  122. package/dist/notesgallery.layered.css +17 -0
  123. package/dist/objectpagemenu.css +3 -0
  124. package/dist/objectpagemenu.d.ts +7 -0
  125. package/dist/objectpagemenu.layered.css +5 -0
  126. package/dist/recordpage.css +59 -0
  127. package/dist/recordpage.layered.css +59 -0
  128. package/dist/recordpicker.css +13 -0
  129. package/dist/recordpicker.d.ts +7 -0
  130. package/dist/recordpicker.layered.css +15 -0
  131. package/dist/savedviews.css +47 -0
  132. package/dist/savedviews.layered.css +47 -0
  133. package/dist/select.css +19 -0
  134. package/dist/select.layered.css +19 -0
  135. package/dist/share.css +84 -0
  136. package/dist/share.d.ts +7 -0
  137. package/dist/share.layered.css +86 -0
  138. package/dist/shortcutssheet.css +24 -0
  139. package/dist/shortcutssheet.d.ts +7 -0
  140. package/dist/shortcutssheet.layered.css +26 -0
  141. package/dist/styles.css +438 -16
  142. package/dist/styles.layered.css +438 -16
  143. package/dist/table.css +7 -2
  144. package/dist/table.layered.css +7 -2
  145. package/dist/taskeditpopover.css +36 -0
  146. package/dist/taskeditpopover.d.ts +7 -0
  147. package/dist/taskeditpopover.layered.css +38 -0
  148. package/dist/tokens.css +26 -0
  149. package/dist/tokens.json +56 -4
  150. package/dist/types/components/breadcrumb/breadcrumb.d.ts +9 -1
  151. package/dist/types/components/button/button.d.ts +2 -0
  152. package/dist/types/components/button/button.recipe.d.ts +12 -0
  153. package/dist/types/components/chip/chip.recipe.d.ts +1 -1
  154. package/dist/types/components/datatable/datatable.d.ts +8 -0
  155. package/dist/types/components/datepickerfield/datepickerfield.d.ts +4 -1
  156. package/dist/types/components/datepickerfield/datepickerfield.recipe.d.ts +18 -3
  157. package/dist/types/components/menu/menu.d.ts +50 -7
  158. package/dist/types/components/multiselect/multiselect.d.ts +9 -0
  159. package/dist/types/components/select/select.d.ts +10 -0
  160. package/dist/types/core/floating-portal.d.ts +6 -5
  161. package/dist/types/core/index.d.ts +1 -1
  162. package/dist/types/core/place-floating.d.ts +37 -0
  163. package/dist/types/index.d.ts +8 -0
  164. package/dist/types/product/assigneepicker/assigneepicker.d.ts +36 -0
  165. package/dist/types/product/assigneepicker/assigneepicker.recipe.d.ts +3 -0
  166. package/dist/types/product/assigneepicker/index.d.ts +2 -0
  167. package/dist/types/product/inbox/inbox.d.ts +13 -1
  168. package/dist/types/product/notesgallery/index.d.ts +2 -0
  169. package/dist/types/product/notesgallery/notesgallery.d.ts +54 -0
  170. package/dist/types/product/notesgallery/notesgallery.recipe.d.ts +3 -0
  171. package/dist/types/product/objectpagemenu/index.d.ts +1 -0
  172. package/dist/types/product/objectpagemenu/objectpagemenu.d.ts +40 -0
  173. package/dist/types/product/objectpagemenu/objectpagemenu.recipe.d.ts +17 -0
  174. package/dist/types/product/objectsettings/objectsettings.d.ts +71 -15
  175. package/dist/types/product/recordpage/index.d.ts +1 -1
  176. package/dist/types/product/recordpage/recordpage.d.ts +142 -1
  177. package/dist/types/product/recordpicker/index.d.ts +2 -0
  178. package/dist/types/product/recordpicker/recordpicker.d.ts +38 -0
  179. package/dist/types/product/recordpicker/recordpicker.recipe.d.ts +3 -0
  180. package/dist/types/product/savedviews/index.d.ts +1 -1
  181. package/dist/types/product/savedviews/savedviews.d.ts +36 -0
  182. package/dist/types/product/share/index.d.ts +2 -0
  183. package/dist/types/product/share/share.d.ts +85 -0
  184. package/dist/types/product/share/share.recipe.d.ts +3 -0
  185. package/dist/types/product/shortcutssheet/index.d.ts +1 -0
  186. package/dist/types/product/shortcutssheet/shortcutssheet.d.ts +49 -0
  187. package/dist/types/product/shortcutssheet/shortcutssheet.recipe.d.ts +3 -0
  188. package/dist/types/product/taskeditpopover/index.d.ts +2 -0
  189. package/dist/types/product/taskeditpopover/taskeditpopover.d.ts +67 -0
  190. package/dist/types/product/taskeditpopover/taskeditpopover.recipe.d.ts +3 -0
  191. package/dist/types/product/workspaceswitchermenu/index.d.ts +1 -0
  192. package/dist/types/product/workspaceswitchermenu/workspaceswitchermenu.d.ts +54 -0
  193. package/dist/types/product/workspaceswitchermenu/workspaceswitchermenu.recipe.d.ts +19 -0
  194. package/dist/types/tokens/contract.d.ts +13 -0
  195. package/dist/types/tokens/palette.d.ts +52 -0
  196. package/dist/types/tokens/semantic.d.ts +20 -0
  197. package/dist/workspaceswitchermenu.css +4 -0
  198. package/dist/workspaceswitchermenu.d.ts +7 -0
  199. package/dist/workspaceswitchermenu.layered.css +6 -0
  200. package/package.json +41 -1
@@ -0,0 +1,125 @@
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.defaultShortcutSections = void 0;
37
+ exports.ShortcutsSheet = ShortcutsSheet;
38
+ const jsx_runtime_1 = require("react/jsx-runtime");
39
+ const lucide_react_1 = require("lucide-react");
40
+ const React = __importStar(require("react"));
41
+ const drawer_1 = require("../../components/drawer");
42
+ const kbd_1 = require("../../components/kbd");
43
+ const core_1 = require("../../core");
44
+ /** The physical Enter/Return key's printed glyph — not a reading-direction
45
+ * indicator (a real keyboard prints the same ↵ shape under any locale), so
46
+ * unlike `LogOut` elsewhere it is deliberately left unmirrored (excused in
47
+ * `build/spec-check.mjs`'s own RTL icon-mirroring ALLOW list). */
48
+ const enterKey = () => (0, jsx_runtime_1.jsx)(lucide_react_1.CornerDownLeft, { size: 16, strokeWidth: 1.75 });
49
+ /**
50
+ * Attio's own canonical keyboard-shortcut list (crisp#615), live-measured
51
+ * off app.attio.com/techpartners' "Keyboard shortcuts" panel (Help →
52
+ * "Shortcuts") — 34 rows across 4 sections. The issue's own quoted table
53
+ * collapsed a few of these ("Navigate to the cell above/right/below/left",
54
+ * "Go to next/previous cell") into one row each; the live panel renders
55
+ * them as separate rows, which is what this list follows.
56
+ */
57
+ exports.defaultShortcutSections = [
58
+ {
59
+ label: "General",
60
+ rows: [
61
+ { description: "Open quick actions", steps: [["⌘", "K"]] },
62
+ { description: "Open search", steps: [["/"]] },
63
+ { description: "Create a new note", steps: [["N"]] },
64
+ { description: "Create a new entry", steps: [["E"]] },
65
+ { description: "Create a new task", steps: [["T"]] },
66
+ { description: "Create a new email", steps: [["C"]] },
67
+ { description: "Go to home page", steps: [["G"], ["H"]] },
68
+ { description: "Go to tasks page", steps: [["G"], ["T"]] },
69
+ { description: "Go to all notes page", steps: [["G"], ["N"]] },
70
+ { description: "Go to all people page", steps: [["G"], ["P"]] },
71
+ { description: "Go to all companies page", steps: [["G"], ["C"]] },
72
+ { description: "Go to email drafts page", steps: [["G"], ["E"]] },
73
+ { description: "Toggle sidebar", steps: [["⌘", "."]] },
74
+ { description: "Navigate up", steps: [["↑"]] },
75
+ { description: "Navigate down", steps: [["↓"]] },
76
+ ],
77
+ },
78
+ {
79
+ label: "Record page",
80
+ rows: [
81
+ { description: "Go to next tab", steps: [["⌥", "→"]] },
82
+ { description: "Go to previous tab", steps: [["⌥", "←"]] },
83
+ ],
84
+ },
85
+ {
86
+ label: "Table view",
87
+ rows: [
88
+ { description: "Navigate to the cell above", steps: [["↑"]] },
89
+ { description: "Navigate to the cell to the right", steps: [["→"]] },
90
+ { description: "Navigate to the cell below", steps: [["↓"]] },
91
+ { description: "Navigate to the cell to the left", steps: [["←"]] },
92
+ { description: "Jump to bottom", steps: [["⌘", "↓"]] },
93
+ { description: "Jump to top", steps: [["⌘", "↑"]] },
94
+ { description: "Select/deselect current row", steps: [["⇧", "␣"]] },
95
+ { description: "Group select rows up", steps: [["⇧", "↑"]] },
96
+ { description: "Group select rows down", steps: [["⇧", "↓"]] },
97
+ { description: "Group select to top", steps: [["⌘", "⇧", "↑"]] },
98
+ { description: "Group select to bottom", steps: [["⌘", "⇧", "↓"]] },
99
+ {
100
+ description: "Open record page for current entry",
101
+ steps: [["⌘", enterKey()]],
102
+ },
103
+ { description: "Select/deselect all rows", steps: [["⌘", "A"]] },
104
+ { description: "Go to next cell", steps: [["⇥"]] },
105
+ { description: "Go to previous cell", steps: [["⇧", "⇥"]] },
106
+ { description: "Edit cell / go to next cell", steps: [[enterKey()]] },
107
+ ],
108
+ },
109
+ {
110
+ label: "Help",
111
+ rows: [{ description: "Open help drawer", steps: [["?"]] }],
112
+ },
113
+ ];
114
+ /**
115
+ * Attio's "Keyboard shortcuts" panel (crisp#615, parity row P-106) — a
116
+ * `Drawer` narrowed to the measured 360px (Drawer's own default is 420px),
117
+ * listing `sections` grouped with a hairline-free 10px row rhythm and a
118
+ * 20px gap before each new section label.
119
+ */
120
+ function ShortcutsSheet({ open, onOpenChange, sections = exports.defaultShortcutSections, title: titleProp, thenLabel: thenLabelProp, closeLabel, className, ...rest }) {
121
+ const title = (0, core_1.useCrispMessage)(titleProp, "Keyboard shortcuts");
122
+ const thenLabel = (0, core_1.useCrispMessage)(thenLabelProp, "then");
123
+ return ((0, jsx_runtime_1.jsx)(drawer_1.Drawer, { open: open, onOpenChange: onOpenChange, title: title, closeLabel: closeLabel, className: (0, core_1.cx)("crisp-shortcutssheet-panel", className), ...rest, children: (0, jsx_runtime_1.jsx)(drawer_1.DrawerBody, { children: (0, jsx_runtime_1.jsx)("div", { className: "crisp-shortcutssheet-body", children: sections.map((section) => ((0, jsx_runtime_1.jsxs)(React.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "crisp-shortcutssheet-section-label", children: section.label }), section.rows.map((row) => ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-shortcutssheet-row", children: [(0, jsx_runtime_1.jsx)("div", { className: "crisp-shortcutssheet-desc", children: row.description }), (0, jsx_runtime_1.jsx)("div", { className: "crisp-shortcutssheet-keys", children: row.steps.map((step, stepIndex) => ((0, jsx_runtime_1.jsxs)(React.Fragment, { children: [stepIndex > 0 && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-shortcutssheet-then", children: thenLabel })), step.map((glyph, glyphIndex) => ((0, jsx_runtime_1.jsx)(kbd_1.Kbd, { children: glyph }, glyphIndex)))] }, stepIndex))) })] }, String(row.description))))] }, String(section.label)))) }) }) }));
124
+ }
125
+ ShortcutsSheet.displayName = "ShortcutsSheet";
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.shortcutssheetRecipe = void 0;
4
+ const core_1 = require("../../core");
5
+ const tokens_1 = require("../../tokens");
6
+ // Attio's "Keyboard shortcuts" panel (crisp#615), live-measured off
7
+ // app.attio.com/techpartners — a second overlay reached from Help →
8
+ // "Shortcuts": 360px wide (narrower than Drawer's own 420px default, hence
9
+ // the width override below), 16px body padding (already Drawer's own
10
+ // `crisp-drawer-body`, unchanged), rows 10px apart, a 20px gap before a new
11
+ // section (expressed as the flex column's own 10px `gap` plus another 10px
12
+ // on every section label but the first, rather than a second gap value),
13
+ // section labels 12px/500, row descriptions 14px/500 — both the SAME
14
+ // `color-mix(fgPrimary, 63%)` muted-text tint RecordPage's own notes already
15
+ // established (crisp#871), and the "then" connector between a sequential
16
+ // shortcut's two steps at 11px/500 in Kbd's own 50%-fgPrimary tint (the
17
+ // same de-emphasis, on the same kind of supporting glyph).
18
+ const config = (0, core_1.defineRecipe)({
19
+ name: "shortcutssheet",
20
+ base: "",
21
+ globalCss: `
22
+ /* Overrides Drawer's own 420px default (specificity: .crisp-drawer
23
+ .crisp-drawer-content.crisp-shortcutssheet-panel, higher than
24
+ Drawer's .crisp-drawer .crisp-drawer-content regardless of which
25
+ chunk of dist/styles.css concatenates first). */
26
+ .crisp-drawer .crisp-drawer-content.crisp-shortcutssheet-panel { width: 360px; }
27
+
28
+ .crisp-shortcutssheet-body { display: flex; flex-direction: column; gap: ${tokens_1.contract.space["2.5"]}; }
29
+ .crisp-shortcutssheet-section-label {
30
+ font-size: ${tokens_1.contract.text.sm}; font-weight: ${tokens_1.contract.weight.medium};
31
+ color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 63%, transparent);
32
+ }
33
+ .crisp-shortcutssheet-section-label:not(:first-child) { margin-top: ${tokens_1.contract.space["2.5"]}; }
34
+ .crisp-shortcutssheet-row { display: flex; align-items: center; justify-content: space-between; gap: ${tokens_1.contract.space["1"]}; }
35
+ .crisp-shortcutssheet-desc {
36
+ font-size: ${tokens_1.contract.text.lg}; font-weight: ${tokens_1.contract.weight.medium};
37
+ color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 63%, transparent);
38
+ }
39
+ .crisp-shortcutssheet-keys { display: flex; align-items: center; gap: ${tokens_1.contract.space["1"]}; flex-shrink: 0; }
40
+ .crisp-shortcutssheet-then {
41
+ font-size: ${tokens_1.contract.text.xs}; font-weight: ${tokens_1.contract.weight.medium};
42
+ color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 50%, transparent);
43
+ }
44
+ `,
45
+ variants: {},
46
+ defaultVariants: {},
47
+ compoundVariants: [],
48
+ });
49
+ exports.shortcutssheetRecipe = (0, core_1.resolveRecipe)(config);
50
+ exports.default = config;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.taskeditpopoverRecipe = exports.TaskEditPopover = void 0;
4
+ var taskeditpopover_1 = require("./taskeditpopover");
5
+ Object.defineProperty(exports, "TaskEditPopover", { enumerable: true, get: function () { return taskeditpopover_1.TaskEditPopover; } });
6
+ var taskeditpopover_recipe_1 = require("./taskeditpopover.recipe");
7
+ Object.defineProperty(exports, "taskeditpopoverRecipe", { enumerable: true, get: function () { return taskeditpopover_recipe_1.taskeditpopoverRecipe; } });
@@ -0,0 +1,159 @@
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.TaskEditPopover = TaskEditPopover;
37
+ const jsx_runtime_1 = require("react/jsx-runtime");
38
+ const lucide_react_1 = require("lucide-react");
39
+ const React = __importStar(require("react"));
40
+ const popover_1 = require("../../components/popover");
41
+ const core_1 = require("../../core");
42
+ const assigneepicker_1 = require("../assigneepicker/assigneepicker");
43
+ const recordpicker_1 = require("../recordpicker/recordpicker");
44
+ const taskeditpopover_recipe_1 = require("./taskeditpopover.recipe");
45
+ /**
46
+ * A task's "Edit task" popover -- measured live on app.attio.com's Tasks
47
+ * page: a checkbox + editable title, then a chip row (due date / assigned /
48
+ * add record), a "more actions" kebab, and Cancel/Save. Composes
49
+ * `AssigneePicker` and `RecordPicker` (both crisp#626) behind their own
50
+ * chips, using the same core floating primitives `Popover` itself is built
51
+ * on rather than `Popover` directly (its content hardcodes a 360px max
52
+ * width, well under this popover's own measured 800px).
53
+ */
54
+ function TaskEditPopover({ trigger, open: openProp, defaultOpen, onOpenChange, title, onTitleChange, done = false, onToggleDone, dueDateLabel, dueDatePicker, assignee = null, users = [], onAssigneeChange, linkedRecordCount = 0, recordCandidates = [], recordCandidatesLoading, onRecordQueryChange, onSelectRecord, menu, onCancel, onSave, headingLabel: headingLabelProp, closeLabel: closeLabelProp, dueDatePlaceholder: dueDatePlaceholderProp, assignLabel: assignLabelProp, assignedToLabel: assignedToLabelProp, addRecordLabel: addRecordLabelProp, linkedRecordLabel: linkedRecordLabelProp, moreActionsLabel: moreActionsLabelProp, cancelLabel: cancelLabelProp, cancelKeyLabel: cancelKeyLabelProp, saveLabel: saveLabelProp, className, }) {
55
+ const headingLabel = (0, core_1.useCrispMessage)(headingLabelProp, "Edit task");
56
+ const closeLabel = (0, core_1.useCrispMessage)(closeLabelProp, "Close");
57
+ const dueDatePlaceholder = (0, core_1.useCrispMessage)(dueDatePlaceholderProp, "Set due date");
58
+ const assignLabel = (0, core_1.useCrispMessage)(assignLabelProp, "Assign");
59
+ const assignedToLabel = (0, core_1.useCrispMessage)(assignedToLabelProp, "Assigned to");
60
+ const addRecordLabel = (0, core_1.useCrispMessage)(addRecordLabelProp, "Add record");
61
+ const linkedRecordLabel = (0, core_1.useCrispMessage)(linkedRecordLabelProp, linkedRecordCount === 1
62
+ ? "1 linked record"
63
+ : `${linkedRecordCount} linked records`);
64
+ const moreActionsLabel = (0, core_1.useCrispMessage)(moreActionsLabelProp, "More actions");
65
+ const cancelLabel = (0, core_1.useCrispMessage)(cancelLabelProp, "Cancel");
66
+ const cancelKeyLabel = (0, core_1.useCrispMessage)(cancelKeyLabelProp, "Esc");
67
+ const saveLabel = (0, core_1.useCrispMessage)(saveLabelProp, "Save");
68
+ const surfaceId = React.useId();
69
+ const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false);
70
+ const open = openProp ?? internalOpen;
71
+ const rootRef = React.useRef(null);
72
+ const triggerRef = React.useRef(null);
73
+ const contentRef = React.useRef(null);
74
+ const [pos, setPos] = React.useState({});
75
+ const setOpen = React.useCallback((next) => {
76
+ if (openProp === undefined)
77
+ setInternalOpen(next);
78
+ onOpenChange?.(next);
79
+ }, [openProp, onOpenChange]);
80
+ const place = () => {
81
+ const el = triggerRef.current;
82
+ if (!el)
83
+ return;
84
+ const { style } = (0, core_1.placeFloating)({
85
+ rect: el.getBoundingClientRect(),
86
+ align: "start",
87
+ gap: 6,
88
+ flipBelow: 300,
89
+ anchor: el,
90
+ });
91
+ setPos(style);
92
+ };
93
+ // biome-ignore lint/correctness/useExhaustiveDependencies: reposition each time it opens
94
+ React.useLayoutEffect(() => {
95
+ if (open)
96
+ place();
97
+ }, [open]);
98
+ React.useEffect(() => {
99
+ if (!open || !contentRef.current)
100
+ return;
101
+ return (0, core_1.registerFloatingLayer)(contentRef.current);
102
+ }, [open]);
103
+ React.useEffect(() => {
104
+ if (!open)
105
+ return;
106
+ const onDown = (e) => {
107
+ const target = e.target;
108
+ if (rootRef.current?.contains(target))
109
+ return;
110
+ if (contentRef.current?.contains(target))
111
+ return;
112
+ if ((0, core_1.isInsideLaterFloatingLayer)(target, contentRef.current))
113
+ return;
114
+ setOpen(false);
115
+ onCancel?.();
116
+ };
117
+ document.addEventListener("pointerdown", onDown);
118
+ return () => document.removeEventListener("pointerdown", onDown);
119
+ }, [open, setOpen, onCancel]);
120
+ const cancel = () => {
121
+ setOpen(false);
122
+ onCancel?.();
123
+ };
124
+ const save = () => {
125
+ setOpen(false);
126
+ onSave?.();
127
+ };
128
+ const triggerEl = React.cloneElement(trigger, {
129
+ ref: triggerRef,
130
+ "aria-haspopup": "dialog",
131
+ "aria-expanded": open,
132
+ "aria-controls": open ? surfaceId : undefined,
133
+ onClick: (e) => {
134
+ trigger.props.onClick?.(e);
135
+ setOpen(!open);
136
+ },
137
+ });
138
+ return ((0, jsx_runtime_1.jsxs)("div", { ref: rootRef, style: { display: "contents" }, children: [triggerEl, open && ((0, jsx_runtime_1.jsx)(core_1.FloatingPortal, { sourceRef: rootRef, children: (0, jsx_runtime_1.jsxs)("div", { ref: contentRef, id: surfaceId, role: "dialog", "aria-label": headingLabel, className: (0, taskeditpopover_recipe_1.taskeditpopoverRecipe)({ className }), style: pos, onKeyDown: (e) => {
139
+ if (e.key === "Escape") {
140
+ e.preventDefault();
141
+ cancel();
142
+ }
143
+ if (e.key === "Enter" &&
144
+ e.metaKey === false &&
145
+ e.ctrlKey === false &&
146
+ e.target.tagName !== "TEXTAREA") {
147
+ // Enter saves, same as Attio's own "Save ⏎" -- but never
148
+ // steals it from a nested picker's own Enter-to-commit.
149
+ if (!(0, core_1.isInsideLaterFloatingLayer)(e.target, contentRef.current)) {
150
+ save();
151
+ }
152
+ }
153
+ }, children: [(0, jsx_runtime_1.jsxs)("div", { className: "crisp-taskeditpopover-header", children: [(0, jsx_runtime_1.jsxs)("span", { className: "crisp-taskeditpopover-heading", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CircleCheckBig, { size: 16, strokeWidth: 1.75 }), headingLabel] }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-taskeditpopover-close", "aria-label": closeLabel, onClick: cancel, children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: 16, strokeWidth: 1.75 }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-taskeditpopover-body", children: [(0, jsx_runtime_1.jsx)("input", { type: "checkbox", className: "crisp-taskeditpopover-check", checked: done, "aria-label": title, onChange: (e) => onToggleDone?.(e.target.checked) }), (0, jsx_runtime_1.jsx)("input", { type: "text", className: "crisp-taskeditpopover-title", value: title, onChange: (e) => onTitleChange?.(e.target.value) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-taskeditpopover-footer", children: [(0, jsx_runtime_1.jsxs)("div", { className: "crisp-taskeditpopover-chips", children: [(0, jsx_runtime_1.jsx)(popover_1.Popover, { align: "start", "aria-label": dueDatePlaceholder, trigger: (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-taskeditpopover-chip", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CalendarDays, { size: 14, strokeWidth: 1.75 }), dueDateLabel ?? dueDatePlaceholder] }), children: dueDatePicker }), (0, jsx_runtime_1.jsx)(popover_1.Popover, { align: "start", "aria-label": assignedToLabel, trigger: (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-taskeditpopover-chip", children: [(0, jsx_runtime_1.jsx)("span", { "aria-hidden": "true", children: "@" }), assignee != null
154
+ ? `${assignedToLabel} ${assignee.name}`
155
+ : assignLabel] }), children: (0, jsx_runtime_1.jsx)(assigneepicker_1.AssigneePicker, { users: users, assignee: assignee, onAssigneeChange: onAssigneeChange }) }), (0, jsx_runtime_1.jsx)(popover_1.Popover, { align: "start", "aria-label": addRecordLabel, trigger: (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-taskeditpopover-chip", children: [(0, jsx_runtime_1.jsx)("span", { "aria-hidden": "true", children: "\u2197" }), linkedRecordCount > 0
156
+ ? linkedRecordLabel
157
+ : addRecordLabel] }), children: (0, jsx_runtime_1.jsx)(recordpicker_1.RecordPicker, { records: recordCandidates, loading: recordCandidatesLoading, onQueryChange: onRecordQueryChange, onSelect: onSelectRecord }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-taskeditpopover-actions", children: [menu != null && ((0, jsx_runtime_1.jsx)(popover_1.Popover, { align: "end", "aria-label": moreActionsLabel, trigger: (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-taskeditpopover-kebab", "aria-label": moreActionsLabel, children: (0, jsx_runtime_1.jsx)(lucide_react_1.MoreHorizontal, { size: 16, strokeWidth: 1.75 }) }), children: menu })), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-taskeditpopover-cancel", onClick: cancel, children: [cancelLabel, (0, jsx_runtime_1.jsx)("kbd", { className: "crisp-taskeditpopover-key", children: cancelKeyLabel })] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-taskeditpopover-save", onClick: save, children: [saveLabel, (0, jsx_runtime_1.jsx)("kbd", { className: "crisp-taskeditpopover-key", children: "\u23CE" })] })] })] })] }) }))] }));
158
+ }
159
+ TaskEditPopover.displayName = "TaskEditPopover";
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.taskeditpopoverRecipe = void 0;
4
+ const core_1 = require("../../core");
5
+ const tokens_1 = require("../../tokens");
6
+ // The "Edit task" popover -- measured live on app.attio.com's Tasks page
7
+ // (click a task row): an 800px-wide floating card, radius 12, a single
8
+ // subtle 1px ring shadow (no blur/offset layer -- lighter than
9
+ // `elevation.floating`, which every other crisp overlay uses; this one
10
+ // really does measure as just the ring, confirmed by walking every
11
+ // ancestor up to the floating root). Same core floating primitives
12
+ // `Popover`/`savedviews` already use directly (this doesn't reuse
13
+ // `Popover` itself: its own `.crisp-popover-content` hardcodes a
14
+ // max-width of min(360px, 92vw), far under this popover's measured width).
15
+ //
16
+ // Three rows: a 44px header (icon+"Edit task", a bottom hairline divider,
17
+ // a close button), a body row (checkbox + editable title), and a 44px
18
+ // footer (the due-date/assigned/add-record chip row on the left, the
19
+ // kebab + Cancel/Save on the right). The chip row's own 10px/400 muted
20
+ // caption size and the footer buttons' matching 10px labels don't fit any
21
+ // existing text-scale token (closest is `text.xs` at 11px) -- raw px per
22
+ // Golden Rule 3's "genuinely intrinsic size" exception, same as
23
+ // `dialog.recipe.ts`'s own submit-key glyphs.
24
+ const config = (0, core_1.defineRecipe)({
25
+ name: "taskeditpopover",
26
+ // Portaled root: position/z-index/the open transition live here as raw
27
+ // literal CSS (not `base`, which lightningcss nests under `.${prefixed}`
28
+ // at BUILD time -- fine for the plain declarations below, but this exact
29
+ // selector text has to exist as source text for `spec-check.mjs`'s
30
+ // overlay-escape/animation scan, the same reason Popover/Menu/Select
31
+ // declare their own portaled root in `globalCss` rather than `base`).
32
+ globalCss: `.crisp-taskeditpopover { position: fixed; z-index: 70; pointer-events: auto; opacity: 1; transform: scale(1); transition: opacity 0.08s ease, transform 0.08s ease; @starting-style { opacity: 0; transform: scale(0.97) translateY(-4px); } }`,
33
+ base: `display: flex; flex-direction: column; box-sizing: border-box; width: 800px; max-width: 92vw; border-radius: ${tokens_1.contract.radius.xl}; background: ${tokens_1.contract.bgSurface}; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.07); font-family: ${tokens_1.contract.font.sans};
34
+ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
35
+
36
+ & .crisp-taskeditpopover-header { display: flex; align-items: center; justify-content: space-between; gap: ${tokens_1.contract.space["2"]}; height: 44px; box-sizing: border-box; padding: 0 ${tokens_1.contract.space["2"]} 0 ${tokens_1.contract.space["3"]}; border-bottom: 1px solid ${tokens_1.contract.borderSubtle}; }
37
+ & .crisp-taskeditpopover-heading { display: flex; align-items: center; gap: ${tokens_1.contract.space["1"]}; font-size: ${tokens_1.contract.text.lg}; font-weight: ${tokens_1.contract.weight.medium}; color: ${tokens_1.contract.fgPrimary}; }
38
+ & .crisp-taskeditpopover-heading svg { flex-shrink: 0; color: ${tokens_1.contract.fgMuted}; }
39
+ & .crisp-taskeditpopover-close { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 28px; height: 28px; margin: 0; padding: 0; border: none; border-radius: ${tokens_1.contract.radius.md}; background: none; color: ${tokens_1.contract.fgMuted}; font-family: inherit; cursor: pointer; }
40
+ & .crisp-taskeditpopover-close:hover { background: ${tokens_1.contract.bgRaised}; color: ${tokens_1.contract.fgPrimary}; }
41
+
42
+ & .crisp-taskeditpopover-body { display: flex; align-items: center; gap: ${tokens_1.contract.space["2.5"]}; min-height: 52px; box-sizing: border-box; padding: ${tokens_1.contract.space["3"]}; }
43
+ & .crisp-taskeditpopover-check { appearance: none; -webkit-appearance: none; box-sizing: border-box; flex-shrink: 0; margin: 0; width: 16px; height: 16px; border: none; border-radius: ${tokens_1.contract.radius.full}; background: ${tokens_1.contract.bgSurface}; box-shadow: inset 0 0 0 1px color-mix(in srgb, ${tokens_1.contract.fgPrimary} 9%, transparent); cursor: pointer; }
44
+ & .crisp-taskeditpopover-check:hover { box-shadow: inset 0 0 0 1px color-mix(in srgb, ${tokens_1.contract.fgPrimary} 30%, transparent); }
45
+ & .crisp-taskeditpopover-check:checked { background: ${tokens_1.contract.bgBrandSolid} center / 10px no-repeat; box-shadow: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.5 5 9l4.5-5'/%3E%3C/svg%3E"); }
46
+ & .crisp-taskeditpopover-title { flex: 1; min-width: 0; border: none; border-radius: ${tokens_1.contract.radius.sm}; outline: none; background: none; font-family: inherit; font-size: ${tokens_1.contract.text.lg}; font-weight: ${tokens_1.contract.weight.medium}; color: ${tokens_1.contract.fgPrimary}; }
47
+ & .crisp-taskeditpopover-title:focus-visible { outline: 2px solid ${tokens_1.contract.strokeFocusRing}; outline-offset: 2px; }
48
+
49
+ & .crisp-taskeditpopover-footer { display: flex; align-items: center; justify-content: space-between; gap: ${tokens_1.contract.space["2"]}; height: 44px; box-sizing: border-box; padding: 0 ${tokens_1.contract.space["2"]} 0 ${tokens_1.contract.space["3"]}; }
50
+ & .crisp-taskeditpopover-chips { display: flex; align-items: center; gap: ${tokens_1.contract.space["1"]}; min-width: 0; }
51
+ & .crisp-taskeditpopover-chip { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; height: 28px; box-sizing: border-box; padding: 4px 8px 4px 6px; border: none; border-radius: ${tokens_1.contract.radius.md}; background: none; color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 55%, transparent); font-family: inherit; font-size: 10px; white-space: nowrap; cursor: pointer; }
52
+ & .crisp-taskeditpopover-chip svg { flex-shrink: 0; }
53
+ & .crisp-taskeditpopover-chip:hover { background: ${tokens_1.contract.bgRaised}; }
54
+
55
+ & .crisp-taskeditpopover-actions { display: flex; align-items: center; gap: ${tokens_1.contract.space["2"]}; flex-shrink: 0; }
56
+ & .crisp-taskeditpopover-kebab { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; margin: 0; padding: 6px; border: none; border-radius: ${tokens_1.contract.radius.md}; background: none; color: ${tokens_1.contract.fgPrimary}; font-family: inherit; cursor: pointer; }
57
+ & .crisp-taskeditpopover-kebab:hover { background: ${tokens_1.contract.bgRaised}; }
58
+ & .crisp-taskeditpopover-cancel { display: inline-flex; align-items: center; gap: 6px; height: 28px; box-sizing: border-box; padding: 4px 6px 4px 8px; border: none; border-radius: ${tokens_1.contract.radius.md}; background: none; color: ${tokens_1.contract.fgPrimary}; font-family: inherit; font-size: 10px; cursor: pointer; }
59
+ & .crisp-taskeditpopover-cancel:hover { background: ${tokens_1.contract.bgRaised}; }
60
+ & .crisp-taskeditpopover-save { display: inline-flex; align-items: center; gap: 6px; height: 28px; box-sizing: border-box; padding: 4px 6px 4px 8px; border: none; border-radius: ${tokens_1.contract.radius.md}; background: ${tokens_1.contract.bgBrandSolid}; color: ${tokens_1.contract.fgOnBrand}; font-family: inherit; font-size: 10px; cursor: pointer; }
61
+ & .crisp-taskeditpopover-save:hover { background: ${tokens_1.contract.bgBrandSolidPressed}; }
62
+ & .crisp-taskeditpopover-key { color: color-mix(in srgb, currentColor 55%, transparent); font-size: 10px; }`,
63
+ variants: {},
64
+ defaultVariants: {},
65
+ compoundVariants: [],
66
+ });
67
+ exports.taskeditpopoverRecipe = (0, core_1.resolveRecipe)(config);
68
+ exports.default = config;
@@ -0,0 +1,17 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./workspaceswitchermenu"), exports);
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkspaceSwitcherMenu = WorkspaceSwitcherMenu;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const lucide_react_1 = require("lucide-react");
6
+ const avatar_1 = require("../../components/avatar");
7
+ const menu_1 = require("../../components/menu");
8
+ const core_1 = require("../../core");
9
+ /**
10
+ * The FIXED content of Attio's own workspace-switcher popover (crisp#632) —
11
+ * live-measured off app.attio.com/techpartners: each workspace as a
12
+ * checked/unchecked row, then New workspace, then Account settings /
13
+ * Workspace settings, then Invite members / Upgrade Attio / Refer another
14
+ * team, then Apps and integrations, then Sign out — each group separated by
15
+ * a hairline, matching a 280px-wide popover.
16
+ *
17
+ * This is CONTENT, not a component with its own trigger/popover: pass it as
18
+ * `Sidebar`'s own `workspaceMenu` prop (crisp#415 already builds the real
19
+ * menu-button trigger/popover machinery around whatever children it's
20
+ * given — the workspace switcher itself has no fixed content of its own by
21
+ * design, since which settings exist is the consumer's; this is that fixed
22
+ * content, ready-made, the same way `defaultCommandItems` is for `Command`).
23
+ */
24
+ function WorkspaceSwitcherMenu({ workspaces, currentWorkspaceId, onSelectWorkspace, onNewWorkspace, onAccountSettings, onWorkspaceSettings, onInviteMembers, onUpgradeAttio, onReferAnotherTeam, onAppsAndIntegrations, onSignOut, newWorkspaceLabel, accountSettingsLabel, workspaceSettingsLabel, inviteMembersLabel, upgradeAttioLabel, referAnotherTeamLabel, appsAndIntegrationsLabel, signOutLabel, }) {
25
+ const newWorkspace = (0, core_1.useCrispMessage)(newWorkspaceLabel, "New workspace");
26
+ const accountSettings = (0, core_1.useCrispMessage)(accountSettingsLabel, "Account settings");
27
+ const workspaceSettings = (0, core_1.useCrispMessage)(workspaceSettingsLabel, "Workspace settings");
28
+ const inviteMembers = (0, core_1.useCrispMessage)(inviteMembersLabel, "Invite members");
29
+ const upgradeAttio = (0, core_1.useCrispMessage)(upgradeAttioLabel, "Upgrade Attio");
30
+ const referAnotherTeam = (0, core_1.useCrispMessage)(referAnotherTeamLabel, "Refer another team");
31
+ const appsAndIntegrations = (0, core_1.useCrispMessage)(appsAndIntegrationsLabel, "Apps and integrations");
32
+ const signOut = (0, core_1.useCrispMessage)(signOutLabel, "Sign out");
33
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [workspaces.map((ws) => {
34
+ const checked = ws.id === currentWorkspaceId;
35
+ return ((0, jsx_runtime_1.jsx)(menu_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(avatar_1.Avatar, { size: "sm", shape: "rounded", tone: ws.avatarTone, children: ws.avatarLabel }), trailingIcon: checked ? ((0, jsx_runtime_1.jsx)(lucide_react_1.CircleCheck, { size: 16, strokeWidth: 1.75, className: "crisp-workspaceswitchermenu-check" })) : undefined, "aria-checked": checked, onSelect: () => onSelectWorkspace?.(ws.id), children: ws.name }, ws.id));
36
+ }), (0, jsx_runtime_1.jsx)(menu_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 16, strokeWidth: 1.75 }), onSelect: onNewWorkspace, children: newWorkspace }), (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.User, { size: 16, strokeWidth: 1.75 }), onSelect: onAccountSettings, children: accountSettings }), (0, jsx_runtime_1.jsx)(menu_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Settings, { size: 16, strokeWidth: 1.75 }), onSelect: onWorkspaceSettings, children: workspaceSettings }), (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.UserPlus, { size: 16, strokeWidth: 1.75 }), onSelect: onInviteMembers, children: inviteMembers }), (0, jsx_runtime_1.jsx)(menu_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.CircleArrowUp, { size: 16, strokeWidth: 1.75 }), onSelect: onUpgradeAttio, children: upgradeAttio }), (0, jsx_runtime_1.jsx)(menu_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.HeartHandshake, { size: 16, strokeWidth: 1.75 }), onSelect: onReferAnotherTeam, children: referAnotherTeam }), (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.Grid2x2, { size: 16, strokeWidth: 1.75 }), onSelect: onAppsAndIntegrations, children: appsAndIntegrations }), (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.LogOut, { "data-rtl-flip": "", size: 16, strokeWidth: 1.75 }), onSelect: onSignOut, children: signOut })] }));
37
+ }
38
+ WorkspaceSwitcherMenu.displayName = "WorkspaceSwitcherMenu";
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.workspaceswitchermenuRecipe = void 0;
4
+ const core_1 = require("../../core");
5
+ const tokens_1 = require("../../tokens");
6
+ /**
7
+ * `WorkspaceSwitcherMenu` owns almost no styling of its own — every visible
8
+ * pixel besides the two rules below is `Menu`/`MenuItem`'s own
9
+ * already-measured recipe (crisp#632):
10
+ * - The RTL mirror for its "Sign out" icon: `LogOut` is treated as
11
+ * direction-bearing (`build/spec-check.mjs`'s own DIRECTIONAL set), so
12
+ * it's marked and mirrored the same way ObjectPageMenu's Notifications
13
+ * chevron is (crisp#616) — see that file's identical recipe for why this
14
+ * is a plain absolute selector, not `${rtlFlipCss}`'s `&`-nesting form.
15
+ * - The current-workspace checkmark's colour: `.crisp-menu-item svg` already
16
+ * sets every menu icon to `fgMuted` (menu.recipe.ts), which is deliberate
17
+ * there but wrong for THIS one glyph — Attio's own is brand-coloured, not
18
+ * muted, to read as a status rather than a plain icon. `svg` doubled in
19
+ * the selector (not just the class) so it outranks that rule under equal
20
+ * source order instead of depending on file concatenation order.
21
+ */
22
+ const config = (0, core_1.defineRecipe)({
23
+ name: "workspaceswitchermenu",
24
+ base: "",
25
+ globalCss: `
26
+ [dir="rtl"] .crisp-menu-item svg[data-rtl-flip] { transform: scaleX(-1); }
27
+ .crisp-menu-item svg.crisp-workspaceswitchermenu-check { color: ${tokens_1.contract.fgBrandContrast}; }
28
+ `,
29
+ variants: {},
30
+ defaultVariants: {},
31
+ compoundVariants: [],
32
+ });
33
+ exports.workspaceswitchermenuRecipe = (0, core_1.resolveRecipe)(config);
34
+ exports.default = config;
@@ -277,4 +277,31 @@ exports.palette = {
277
277
  // s3 (shadow.yaml) -- the listbox's single-layer floating shadow, in place
278
278
  // of crisp's own multi-layer `elevation.floating` for this component only.
279
279
  selectShadow: { light: "#0000001f", dark: "#000000cc" },
280
+ // your-moon/crisp#998: the 12-colour tag/option-colour palette a workspace
281
+ // admin picks for a Select/MultiSelect option, measured live off
282
+ // app.attio.com's Categories multi-select field (table-cell/column-editor
283
+ // pill, not the larger tinted-text activity-feed variant -- see
284
+ // ~/grc-parity/attio-tag-palette.md). All 12 are near-white pastels with
285
+ // flat black text regardless of which one -- Attio's theme toggle is
286
+ // off-limits (same restriction every other raw entry in this file notes),
287
+ // so no dark variant was reachable; light is reused for dark, same as
288
+ // `cyan600`/`purple600`/`orange600` above already do for the same reason.
289
+ // Numbered 1-12 rather than named: Attio assigns them by an internal hash
290
+ // of the option's id, not by any hue name a consumer would recognise.
291
+ tagSwatch1: { light: "#fff3cc", dark: "#fff3cc" },
292
+ tagSwatch2: { light: "#f4fbcb", dark: "#f4fbcb" },
293
+ tagSwatch3: { light: "#fdf7c4", dark: "#fdf7c4" },
294
+ tagSwatch4: { light: "#feecf3", dark: "#feecf3" },
295
+ tagSwatch5: { light: "#e0fced", dark: "#e0fced" },
296
+ tagSwatch6: { light: "#ddf7ff", dark: "#ddf7ff" },
297
+ tagSwatch7: { light: "#f6f7f7", dark: "#f6f7f7" },
298
+ tagSwatch8: { light: "#ffebeb", dark: "#ffebeb" },
299
+ tagSwatch9: { light: "#feeee1", dark: "#feeee1" },
300
+ tagSwatch10: { light: "#e5eeff", dark: "#e5eeff" },
301
+ tagSwatch11: { light: "#f5f0ff", dark: "#f5f0ff" },
302
+ tagSwatch12: { light: "#fdedff", dark: "#fdedff" },
303
+ // measured alongside the palette above: flat opaque black, not `ink`
304
+ // (#101112) -- a genuinely different, slightly darker hex Attio uses only
305
+ // for this one pill's text, regardless of which of the 12 backgrounds.
306
+ tagSwatchInk: { light: "#000000", dark: "#000000" },
280
307
  };
@@ -129,4 +129,24 @@ exports.semantic = {
129
129
  strokeSelectDivider: "selectDivider",
130
130
  fgSelectPlaceholder: "selectPlaceholder",
131
131
  shadowSelect: "selectShadow",
132
+ /** your-moon/crisp#998: a Select/MultiSelect option's fixed tag colour
133
+ * (`swatch`, 1-12) -- see palette.ts's own comment on `tagSwatch1` for
134
+ * the measurement. Distinct from `Select`'s existing `color` (an
135
+ * arbitrary-CSS status dot) and `MultiSelect`'s existing `tone` (crisp's
136
+ * own semantic 7-tone chip family): this is Attio's own enumerable,
137
+ * workspace-admin-assigned palette, reproduced verbatim rather than
138
+ * mapped onto either existing mechanism. */
139
+ bgTagSwatch1: "tagSwatch1",
140
+ bgTagSwatch2: "tagSwatch2",
141
+ bgTagSwatch3: "tagSwatch3",
142
+ bgTagSwatch4: "tagSwatch4",
143
+ bgTagSwatch5: "tagSwatch5",
144
+ bgTagSwatch6: "tagSwatch6",
145
+ bgTagSwatch7: "tagSwatch7",
146
+ bgTagSwatch8: "tagSwatch8",
147
+ bgTagSwatch9: "tagSwatch9",
148
+ bgTagSwatch10: "tagSwatch10",
149
+ bgTagSwatch11: "tagSwatch11",
150
+ bgTagSwatch12: "tagSwatch12",
151
+ fgTagSwatch: "tagSwatchInk",
132
152
  };