@crisp-ui-kit/crisp 0.57.3 → 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.
- package/dist/assigneepicker.css +13 -0
- package/dist/assigneepicker.d.ts +7 -0
- package/dist/assigneepicker.layered.css +15 -0
- package/dist/button.css +1 -1
- package/dist/button.layered.css +1 -1
- package/dist/cjs/components/button/button.recipe.js +15 -10
- package/dist/cjs/components/datatable/datatable.js +6 -3
- package/dist/cjs/components/datatable/datatable.recipe.js +35 -2
- package/dist/cjs/components/menu/menu.js +48 -8
- package/dist/cjs/components/multiselect/multiselect.js +3 -0
- package/dist/cjs/components/multiselect/multiselect.recipe.js +18 -0
- package/dist/cjs/components/select/select.js +2 -2
- package/dist/cjs/components/select/select.recipe.js +19 -0
- package/dist/cjs/core/index.js +2 -1
- package/dist/cjs/core/place-floating.js +38 -0
- package/dist/cjs/index.js +8 -0
- package/dist/cjs/product/assigneepicker/assigneepicker.js +127 -0
- package/dist/cjs/product/assigneepicker/assigneepicker.recipe.js +36 -0
- package/dist/cjs/product/assigneepicker/index.js +7 -0
- package/dist/cjs/product/notesgallery/index.js +7 -0
- package/dist/cjs/product/notesgallery/notesgallery.js +80 -0
- package/dist/cjs/product/notesgallery/notesgallery.recipe.js +46 -0
- package/dist/cjs/product/objectpagemenu/index.js +17 -0
- package/dist/cjs/product/objectpagemenu/objectpagemenu.js +26 -0
- package/dist/cjs/product/objectpagemenu/objectpagemenu.recipe.js +30 -0
- package/dist/cjs/product/objectsettings/objectsettings.js +107 -14
- package/dist/cjs/product/recordpage/recordpage.js +64 -5
- package/dist/cjs/product/recordpage/recordpage.recipe.js +38 -0
- package/dist/cjs/product/recordpicker/index.js +7 -0
- package/dist/cjs/product/recordpicker/recordpicker.js +100 -0
- package/dist/cjs/product/recordpicker/recordpicker.recipe.js +36 -0
- package/dist/cjs/product/savedviews/index.js +2 -1
- package/dist/cjs/product/savedviews/savedviews.js +22 -0
- package/dist/cjs/product/savedviews/savedviews.recipe.js +47 -0
- package/dist/cjs/product/share/index.js +7 -0
- package/dist/cjs/product/share/share.js +179 -0
- package/dist/cjs/product/share/share.recipe.js +114 -0
- package/dist/cjs/product/shortcutssheet/index.js +17 -0
- package/dist/cjs/product/shortcutssheet/shortcutssheet.js +125 -0
- package/dist/cjs/product/shortcutssheet/shortcutssheet.recipe.js +50 -0
- package/dist/cjs/product/taskeditpopover/index.js +7 -0
- package/dist/cjs/product/taskeditpopover/taskeditpopover.js +159 -0
- package/dist/cjs/product/taskeditpopover/taskeditpopover.recipe.js +68 -0
- package/dist/cjs/product/workspaceswitchermenu/index.js +17 -0
- package/dist/cjs/product/workspaceswitchermenu/workspaceswitchermenu.js +38 -0
- package/dist/cjs/product/workspaceswitchermenu/workspaceswitchermenu.recipe.js +34 -0
- package/dist/cjs/tokens/palette.js +27 -0
- package/dist/cjs/tokens/semantic.js +20 -0
- package/dist/datatable.css +40 -7
- package/dist/datatable.layered.css +40 -7
- package/dist/esm/components/button/button.recipe.js +15 -10
- package/dist/esm/components/datatable/datatable.js +6 -3
- package/dist/esm/components/datatable/datatable.recipe.js +35 -2
- package/dist/esm/components/menu/menu.js +47 -7
- package/dist/esm/components/multiselect/multiselect.js +3 -0
- package/dist/esm/components/multiselect/multiselect.recipe.js +18 -0
- package/dist/esm/components/select/select.js +2 -2
- package/dist/esm/components/select/select.recipe.js +19 -0
- package/dist/esm/core/index.js +1 -1
- package/dist/esm/core/place-floating.js +37 -0
- package/dist/esm/index.js +8 -0
- package/dist/esm/product/assigneepicker/assigneepicker.js +91 -0
- package/dist/esm/product/assigneepicker/assigneepicker.recipe.js +33 -0
- package/dist/esm/product/assigneepicker/index.js +2 -0
- package/dist/esm/product/notesgallery/index.js +2 -0
- package/dist/esm/product/notesgallery/notesgallery.js +44 -0
- package/dist/esm/product/notesgallery/notesgallery.recipe.js +43 -0
- package/dist/esm/product/objectpagemenu/index.js +1 -0
- package/dist/esm/product/objectpagemenu/objectpagemenu.js +23 -0
- package/dist/esm/product/objectpagemenu/objectpagemenu.recipe.js +27 -0
- package/dist/esm/product/objectsettings/objectsettings.js +106 -13
- package/dist/esm/product/recordpage/recordpage.js +64 -5
- package/dist/esm/product/recordpage/recordpage.recipe.js +38 -0
- package/dist/esm/product/recordpicker/index.js +2 -0
- package/dist/esm/product/recordpicker/recordpicker.js +64 -0
- package/dist/esm/product/recordpicker/recordpicker.recipe.js +33 -0
- package/dist/esm/product/savedviews/index.js +1 -1
- package/dist/esm/product/savedviews/savedviews.js +22 -1
- package/dist/esm/product/savedviews/savedviews.recipe.js +47 -0
- package/dist/esm/product/share/index.js +2 -0
- package/dist/esm/product/share/share.js +143 -0
- package/dist/esm/product/share/share.recipe.js +111 -0
- package/dist/esm/product/shortcutssheet/index.js +1 -0
- package/dist/esm/product/shortcutssheet/shortcutssheet.js +88 -0
- package/dist/esm/product/shortcutssheet/shortcutssheet.recipe.js +47 -0
- package/dist/esm/product/taskeditpopover/index.js +2 -0
- package/dist/esm/product/taskeditpopover/taskeditpopover.js +123 -0
- package/dist/esm/product/taskeditpopover/taskeditpopover.recipe.js +65 -0
- package/dist/esm/product/workspaceswitchermenu/index.js +1 -0
- package/dist/esm/product/workspaceswitchermenu/workspaceswitchermenu.js +35 -0
- package/dist/esm/product/workspaceswitchermenu/workspaceswitchermenu.recipe.js +31 -0
- package/dist/esm/tokens/palette.js +27 -0
- package/dist/esm/tokens/semantic.js +20 -0
- package/dist/multiselect.css +18 -0
- package/dist/multiselect.layered.css +18 -0
- package/dist/native/tokens.d.ts +1 -1
- package/dist/native/tokens.js +56 -4
- package/dist/notesgallery.css +15 -0
- package/dist/notesgallery.d.ts +7 -0
- package/dist/notesgallery.layered.css +17 -0
- package/dist/objectpagemenu.css +3 -0
- package/dist/objectpagemenu.d.ts +7 -0
- package/dist/objectpagemenu.layered.css +5 -0
- package/dist/recordpage.css +36 -0
- package/dist/recordpage.layered.css +36 -0
- package/dist/recordpicker.css +13 -0
- package/dist/recordpicker.d.ts +7 -0
- package/dist/recordpicker.layered.css +15 -0
- package/dist/savedviews.css +47 -0
- package/dist/savedviews.layered.css +47 -0
- package/dist/select.css +19 -0
- package/dist/select.layered.css +19 -0
- package/dist/share.css +84 -0
- package/dist/share.d.ts +7 -0
- package/dist/share.layered.css +86 -0
- package/dist/shortcutssheet.css +24 -0
- package/dist/shortcutssheet.d.ts +7 -0
- package/dist/shortcutssheet.layered.css +26 -0
- package/dist/styles.css +387 -8
- package/dist/styles.layered.css +387 -8
- package/dist/taskeditpopover.css +36 -0
- package/dist/taskeditpopover.d.ts +7 -0
- package/dist/taskeditpopover.layered.css +38 -0
- package/dist/tokens.css +26 -0
- package/dist/tokens.json +56 -4
- package/dist/types/components/button/button.recipe.d.ts +2 -3
- package/dist/types/components/datatable/datatable.d.ts +8 -0
- package/dist/types/components/menu/menu.d.ts +50 -7
- package/dist/types/components/multiselect/multiselect.d.ts +9 -0
- package/dist/types/components/select/select.d.ts +10 -0
- package/dist/types/core/index.d.ts +1 -1
- package/dist/types/core/place-floating.d.ts +37 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/product/assigneepicker/assigneepicker.d.ts +36 -0
- package/dist/types/product/assigneepicker/assigneepicker.recipe.d.ts +3 -0
- package/dist/types/product/assigneepicker/index.d.ts +2 -0
- package/dist/types/product/notesgallery/index.d.ts +2 -0
- package/dist/types/product/notesgallery/notesgallery.d.ts +54 -0
- package/dist/types/product/notesgallery/notesgallery.recipe.d.ts +3 -0
- package/dist/types/product/objectpagemenu/index.d.ts +1 -0
- package/dist/types/product/objectpagemenu/objectpagemenu.d.ts +40 -0
- package/dist/types/product/objectpagemenu/objectpagemenu.recipe.d.ts +17 -0
- package/dist/types/product/objectsettings/objectsettings.d.ts +71 -15
- package/dist/types/product/recordpage/index.d.ts +1 -1
- package/dist/types/product/recordpage/recordpage.d.ts +96 -1
- package/dist/types/product/recordpicker/index.d.ts +2 -0
- package/dist/types/product/recordpicker/recordpicker.d.ts +38 -0
- package/dist/types/product/recordpicker/recordpicker.recipe.d.ts +3 -0
- package/dist/types/product/savedviews/index.d.ts +1 -1
- package/dist/types/product/savedviews/savedviews.d.ts +36 -0
- package/dist/types/product/share/index.d.ts +2 -0
- package/dist/types/product/share/share.d.ts +85 -0
- package/dist/types/product/share/share.recipe.d.ts +3 -0
- package/dist/types/product/shortcutssheet/index.d.ts +1 -0
- package/dist/types/product/shortcutssheet/shortcutssheet.d.ts +49 -0
- package/dist/types/product/shortcutssheet/shortcutssheet.recipe.d.ts +3 -0
- package/dist/types/product/taskeditpopover/index.d.ts +2 -0
- package/dist/types/product/taskeditpopover/taskeditpopover.d.ts +67 -0
- package/dist/types/product/taskeditpopover/taskeditpopover.recipe.d.ts +3 -0
- package/dist/types/product/workspaceswitchermenu/index.d.ts +1 -0
- package/dist/types/product/workspaceswitchermenu/workspaceswitchermenu.d.ts +54 -0
- package/dist/types/product/workspaceswitchermenu/workspaceswitchermenu.recipe.d.ts +19 -0
- package/dist/types/tokens/contract.d.ts +13 -0
- package/dist/types/tokens/palette.d.ts +52 -0
- package/dist/types/tokens/semantic.d.ts +20 -0
- package/dist/workspaceswitchermenu.css +4 -0
- package/dist/workspaceswitchermenu.d.ts +7 -0
- package/dist/workspaceswitchermenu.layered.css +6 -0
- package/package.json +41 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
.crisp-assigneepicker {
|
|
2
|
+
display: flex; flex-direction: column; box-sizing: border-box; width: 350px; font-family: var(--crisp-font-sans);
|
|
3
|
+
& .crisp-assigneepicker-search { display: flex; align-items: center; gap: var(--crisp-space-2); height: 36px; padding: 0 var(--crisp-space-3); color: var(--crisp-fg-muted); }
|
|
4
|
+
& .crisp-assigneepicker-search svg { flex-shrink: 0; }
|
|
5
|
+
& .crisp-assigneepicker-search-input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); line-height: 20px; color: var(--crisp-fg-primary); }
|
|
6
|
+
& .crisp-assigneepicker-search-input::placeholder { color: var(--crisp-fg-muted); }
|
|
7
|
+
& .crisp-assigneepicker-pill { display: flex; padding: 0 var(--crisp-space-3) var(--crisp-space-2); }
|
|
8
|
+
& .crisp-assigneepicker-remove { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 14px; height: 14px; margin: 0; padding: 0; border: none; background: none; color: inherit; font-family: inherit; cursor: pointer; }
|
|
9
|
+
& .crisp-assigneepicker-empty { padding: var(--crisp-space-4) var(--crisp-space-3); text-align: center; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
10
|
+
& .crisp-assigneepicker-list { display: flex; flex-direction: column; margin: 0; padding: var(--crisp-space-1); list-style: none; }
|
|
11
|
+
& .crisp-assigneepicker-option { display: flex; align-items: center; width: 100%; box-sizing: border-box; height: 32px; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: none; font-family: inherit; text-align: start; cursor: pointer; }
|
|
12
|
+
& .crisp-assigneepicker-option:hover, & .crisp-assigneepicker-option[data-highlighted] { background: var(--crisp-bg-raised); }
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
@layer crisp-components {
|
|
2
|
+
.crisp-assigneepicker {
|
|
3
|
+
display: flex; flex-direction: column; box-sizing: border-box; width: 350px; font-family: var(--crisp-font-sans);
|
|
4
|
+
& .crisp-assigneepicker-search { display: flex; align-items: center; gap: var(--crisp-space-2); height: 36px; padding: 0 var(--crisp-space-3); color: var(--crisp-fg-muted); }
|
|
5
|
+
& .crisp-assigneepicker-search svg { flex-shrink: 0; }
|
|
6
|
+
& .crisp-assigneepicker-search-input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); line-height: 20px; color: var(--crisp-fg-primary); }
|
|
7
|
+
& .crisp-assigneepicker-search-input::placeholder { color: var(--crisp-fg-muted); }
|
|
8
|
+
& .crisp-assigneepicker-pill { display: flex; padding: 0 var(--crisp-space-3) var(--crisp-space-2); }
|
|
9
|
+
& .crisp-assigneepicker-remove { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 14px; height: 14px; margin: 0; padding: 0; border: none; background: none; color: inherit; font-family: inherit; cursor: pointer; }
|
|
10
|
+
& .crisp-assigneepicker-empty { padding: var(--crisp-space-4) var(--crisp-space-3); text-align: center; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
11
|
+
& .crisp-assigneepicker-list { display: flex; flex-direction: column; margin: 0; padding: var(--crisp-space-1); list-style: none; }
|
|
12
|
+
& .crisp-assigneepicker-option { display: flex; align-items: center; width: 100%; box-sizing: border-box; height: 32px; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: none; font-family: inherit; text-align: start; cursor: pointer; }
|
|
13
|
+
& .crisp-assigneepicker-option:hover, & .crisp-assigneepicker-option[data-highlighted] { background: var(--crisp-bg-raised); }
|
|
14
|
+
}
|
|
15
|
+
}
|
package/dist/button.css
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
height: 24px; padding-inline: var(--crisp-space-1-5); font-size: var(--crisp-text-md); border-radius: var(--crisp-radius-md);
|
|
26
26
|
}
|
|
27
27
|
.crisp-button--size_xs {
|
|
28
|
-
height: 20px; padding-inline: var(--crisp-space-1-5); font-size:
|
|
28
|
+
height: 20px; padding-inline: var(--crisp-space-1-5); font-size: var(--crisp-text-sm); line-height: 16px; letter-spacing: normal; border-radius: var(--crisp-radius-sm); gap: var(--crisp-space-1);
|
|
29
29
|
}
|
|
30
30
|
.crisp-button--size_md {
|
|
31
31
|
height: 28px; padding-inline: var(--crisp-space-2); font-size: var(--crisp-text-lg); border-radius: var(--crisp-radius-md);
|
package/dist/button.layered.css
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
height: 24px; padding-inline: var(--crisp-space-1-5); font-size: var(--crisp-text-md); border-radius: var(--crisp-radius-md);
|
|
27
27
|
}
|
|
28
28
|
.crisp-button--size_xs {
|
|
29
|
-
height: 20px; padding-inline: var(--crisp-space-1-5); font-size:
|
|
29
|
+
height: 20px; padding-inline: var(--crisp-space-1-5); font-size: var(--crisp-text-sm); line-height: 16px; letter-spacing: normal; border-radius: var(--crisp-radius-sm); gap: var(--crisp-space-1);
|
|
30
30
|
}
|
|
31
31
|
.crisp-button--size_md {
|
|
32
32
|
height: 28px; padding-inline: var(--crisp-space-2); font-size: var(--crisp-text-lg); border-radius: var(--crisp-radius-md);
|
|
@@ -135,19 +135,24 @@ const spec = (0, core_1.defineSpec)({
|
|
|
135
135
|
// shape="icon" already does for every other size, so it needs no
|
|
136
136
|
// extra rule), 4px gap between multiple children.
|
|
137
137
|
//
|
|
138
|
-
//
|
|
139
|
-
//
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
138
|
+
// Follow-up correction (still #688): the label is 12px/500(medium)/
|
|
139
|
+
// 16px line-height/normal tracking -- NOT #682's 14px button tracking,
|
|
140
|
+
// and NOT the 10px/regular/15px this file shipped with first. That
|
|
141
|
+
// first pass read getComputedStyle on the `<button>` element itself;
|
|
142
|
+
// Attio's actual label lives in an inner `<div>` that overrides
|
|
143
|
+
// font-size/weight/line-height on top of it (confirmed by walking the
|
|
144
|
+
// full child tree, on "View all" AND "Today, <date>", both Home and
|
|
145
|
+
// the savedviews toolbar's own "Save for everyone") -- the outer
|
|
146
|
+
// button's own 10px/400/15px is real but never what's on screen.
|
|
147
|
+
// 12px is already `c.text.sm` and 500 is already the base's own
|
|
148
|
+
// default `fontWeight` (no override needed for either); only
|
|
149
|
+
// line-height and tracking still diverge from the base's 20px/
|
|
150
|
+
// -0.07px and need their own values here.
|
|
145
151
|
xs: {
|
|
146
152
|
height: "20px",
|
|
147
153
|
paddingInline: tokens_1.contract.space["1.5"],
|
|
148
|
-
fontSize:
|
|
149
|
-
|
|
150
|
-
lineHeight: "15px",
|
|
154
|
+
fontSize: tokens_1.contract.text.sm,
|
|
155
|
+
lineHeight: "16px",
|
|
151
156
|
letterSpacing: "normal",
|
|
152
157
|
borderRadius: tokens_1.contract.radius.sm,
|
|
153
158
|
gap: tokens_1.contract.space["1"],
|
|
@@ -428,14 +428,17 @@ function renderTyped(col, value, avatarTone, row, display, locale = "en-US", ope
|
|
|
428
428
|
const tags = Array.isArray(value) ? value : [];
|
|
429
429
|
if (!tags.length)
|
|
430
430
|
return empty;
|
|
431
|
-
return ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-tags", children: tags.map((t) => ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-tag", "data-tone": col.tones?.[t] ?? toneFor(t), children: t }, t))) }));
|
|
431
|
+
return ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-tags", children: tags.map((t) => col.swatches?.[t] ? ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-swatch", "data-swatch": col.swatches[t], children: t }, t)) : ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-tag", "data-tone": col.tones?.[t] ?? toneFor(t), children: t }, t))) }));
|
|
432
432
|
}
|
|
433
433
|
case "status": {
|
|
434
434
|
const s = asText(value);
|
|
435
435
|
if (!s)
|
|
436
436
|
return empty;
|
|
437
|
-
// tone is looked up by the RAW status, so formatting the label
|
|
438
|
-
// translation) can never silently repaint the chip
|
|
437
|
+
// tone/swatch is looked up by the RAW status, so formatting the label
|
|
438
|
+
// (casing, translation) can never silently repaint the chip
|
|
439
|
+
if (col.swatches?.[s]) {
|
|
440
|
+
return ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-swatch", "data-swatch": col.swatches[s], children: display || s }));
|
|
441
|
+
}
|
|
439
442
|
return ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-tag", "data-tone": col.tones?.[s] ?? toneFor(s), children: display || s }));
|
|
440
443
|
}
|
|
441
444
|
case "rating": {
|
|
@@ -318,9 +318,24 @@ const config = (0, core_1.defineRecipe)({
|
|
|
318
318
|
Avatar's own already-shipped shape="rounded" value, not a new number.
|
|
319
319
|
shape="circle" reuses Avatar's own shape="circle" value (radius.full)
|
|
320
320
|
the same way, measured live on a real Attio person avatar. */
|
|
321
|
-
& .crisp-datatable-avatar { width: ${tokens_1.contract.size.icon}; height: ${tokens_1.contract.size.icon}; border-radius: 30%; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; font-weight: ${tokens_1.contract.weight.semibold}; text-transform: uppercase; color: ${tokens_1.contract.
|
|
321
|
+
& .crisp-datatable-avatar { width: ${tokens_1.contract.size.icon}; height: ${tokens_1.contract.size.icon}; border-radius: 30%; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; font-weight: ${tokens_1.contract.weight.semibold}; text-transform: uppercase; color: ${tokens_1.contract.fgOnTone}; background: ${tokens_1.contract.bgBrandSolid}; }
|
|
322
322
|
& .crisp-datatable-avatar[data-shape="circle"] { border-radius: ${tokens_1.contract.radius.full}; }
|
|
323
|
-
|
|
323
|
+
/* your-moon/crisp#891: every data-tone override painted ONLY a
|
|
324
|
+
background, inheriting the base rule's white fgOnBrand -- white
|
|
325
|
+
clears AA against none of these seven fills (brand 3.23:1, success
|
|
326
|
+
3.96, warning 4.12, danger 3.76, purple 3.58, cyan 2.30, orange
|
|
327
|
+
2.77). fgOnTone (ink, #101112 -- semantic.ts's own comment: "dark ink
|
|
328
|
+
clears AA on every tone in both themes") clears 4.5:1+ on every fill
|
|
329
|
+
here with a comfortable margin (brand 5.85, success 4.77/6.29,
|
|
330
|
+
danger 5.03/6.19, purple 5.27, cyan 8.23, orange 6.83, light/dark),
|
|
331
|
+
so the base rule's colour moves there and every override keeps it --
|
|
332
|
+
EXCEPT warning, whose raw fill (bgWarning) only clears 4.59:1 in
|
|
333
|
+
light, too thin a margin to rely on: it takes bgWarningSolid instead,
|
|
334
|
+
the same solid-warning-plus-ink pair Badge's own solid variant
|
|
335
|
+
already established (13.98/7.83), for the same reason (see
|
|
336
|
+
tokens/palette.ts's amberSolid comment). No background changes
|
|
337
|
+
otherwise -- the fills themselves are unaffected, only the text. */
|
|
338
|
+
& .crisp-datatable-avatar[data-tone="success"] { background: ${tokens_1.contract.bgSuccess}; color: ${tokens_1.contract.fgOnTone}; } & .crisp-datatable-avatar[data-tone="warning"] { background: ${tokens_1.contract.bgWarningSolid}; color: ${tokens_1.contract.fgOnTone}; } & .crisp-datatable-avatar[data-tone="danger"] { background: ${tokens_1.contract.bgDanger}; color: ${tokens_1.contract.fgOnTone}; } & .crisp-datatable-avatar[data-tone="purple"] { background: ${tokens_1.contract.bgPurple}; color: ${tokens_1.contract.fgOnTone}; } & .crisp-datatable-avatar[data-tone="cyan"] { background: ${tokens_1.contract.bgCyan}; color: ${tokens_1.contract.fgOnTone}; } & .crisp-datatable-avatar[data-tone="orange"] { background: ${tokens_1.contract.bgOrange}; color: ${tokens_1.contract.fgOnTone}; }
|
|
324
339
|
& .crisp-datatable-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
|
|
325
340
|
& .crisp-datatable-tags { display: flex; align-items: center; gap: ${tokens_1.contract.space["1"]}; overflow: hidden; }
|
|
326
341
|
& .crisp-datatable-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); }
|
|
@@ -331,6 +346,24 @@ const config = (0, core_1.defineRecipe)({
|
|
|
331
346
|
& .crisp-datatable-tag[data-tone="purple"] { background: color-mix(in srgb, ${tokens_1.contract.bgPurple} 16%, transparent); color: color-mix(in srgb, ${tokens_1.contract.bgPurple} 80%, ${tokens_1.contract.fgPrimary}); }
|
|
332
347
|
& .crisp-datatable-tag[data-tone="cyan"] { background: color-mix(in srgb, ${tokens_1.contract.bgCyan} 18%, transparent); color: color-mix(in srgb, ${tokens_1.contract.bgCyan} 82%, ${tokens_1.contract.fgPrimary}); }
|
|
333
348
|
& .crisp-datatable-tag[data-tone="orange"] { background: color-mix(in srgb, ${tokens_1.contract.bgOrange} 16%, transparent); color: color-mix(in srgb, ${tokens_1.contract.bgOrange} 82%, ${tokens_1.contract.fgPrimary}); }
|
|
349
|
+
/* your-moon/crisp#998: Attio's own 12-colour tag palette (measured
|
|
350
|
+
live, see tokens/palette.ts's tagSwatch1 comment) -- flat black
|
|
351
|
+
text, no ring, unlike the tone family above. 7px radius/10px text
|
|
352
|
+
are measured literals (no matching step in the shared scale, same
|
|
353
|
+
as Select's own .crisp-select-swatch). */
|
|
354
|
+
& .crisp-datatable-swatch { display: inline-flex; align-items: center; height: ${tokens_1.contract.size.chip}; padding: 0 ${tokens_1.contract.space["1"]}; border-radius: 7px; font-size: 10px; font-weight: ${tokens_1.contract.weight.regular}; white-space: nowrap; color: ${tokens_1.contract.fgTagSwatch}; }
|
|
355
|
+
& .crisp-datatable-swatch[data-swatch="1"] { background: ${tokens_1.contract.bgTagSwatch1}; }
|
|
356
|
+
& .crisp-datatable-swatch[data-swatch="2"] { background: ${tokens_1.contract.bgTagSwatch2}; }
|
|
357
|
+
& .crisp-datatable-swatch[data-swatch="3"] { background: ${tokens_1.contract.bgTagSwatch3}; }
|
|
358
|
+
& .crisp-datatable-swatch[data-swatch="4"] { background: ${tokens_1.contract.bgTagSwatch4}; }
|
|
359
|
+
& .crisp-datatable-swatch[data-swatch="5"] { background: ${tokens_1.contract.bgTagSwatch5}; }
|
|
360
|
+
& .crisp-datatable-swatch[data-swatch="6"] { background: ${tokens_1.contract.bgTagSwatch6}; }
|
|
361
|
+
& .crisp-datatable-swatch[data-swatch="7"] { background: ${tokens_1.contract.bgTagSwatch7}; }
|
|
362
|
+
& .crisp-datatable-swatch[data-swatch="8"] { background: ${tokens_1.contract.bgTagSwatch8}; }
|
|
363
|
+
& .crisp-datatable-swatch[data-swatch="9"] { background: ${tokens_1.contract.bgTagSwatch9}; }
|
|
364
|
+
& .crisp-datatable-swatch[data-swatch="10"] { background: ${tokens_1.contract.bgTagSwatch10}; }
|
|
365
|
+
& .crisp-datatable-swatch[data-swatch="11"] { background: ${tokens_1.contract.bgTagSwatch11}; }
|
|
366
|
+
& .crisp-datatable-swatch[data-swatch="12"] { background: ${tokens_1.contract.bgTagSwatch12}; }
|
|
334
367
|
& .crisp-datatable-num { font-variant-numeric: tabular-nums; }
|
|
335
368
|
& .crisp-datatable-muted { color: ${tokens_1.contract.fgMuted}; }
|
|
336
369
|
/* crisp#822 -- a date/datetime cell's danger/overdue tone: same token as
|
|
@@ -33,8 +33,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.MenuItem = void 0;
|
|
36
37
|
exports.Menu = Menu;
|
|
37
|
-
exports.MenuItem = MenuItem;
|
|
38
38
|
exports.MenuCheckboxItem = MenuCheckboxItem;
|
|
39
39
|
exports.MenuSeparator = MenuSeparator;
|
|
40
40
|
exports.MenuLabel = MenuLabel;
|
|
@@ -52,7 +52,7 @@ const MenuContext = React.createContext(null);
|
|
|
52
52
|
* typeahead, Enter/Space select, Esc closes and returns focus to the trigger);
|
|
53
53
|
* closes on outside click. Flips up / right-aligns when space is tight.
|
|
54
54
|
*/
|
|
55
|
-
function Menu({ trigger, children, align = "start", open: openProp, defaultOpen, onOpenChange, className, contentClassName, "aria-label": ariaLabel, }) {
|
|
55
|
+
function Menu({ trigger, children, align = "start", placement = "menu", open: openProp, defaultOpen, onOpenChange, className, contentClassName, "aria-label": ariaLabel, }) {
|
|
56
56
|
// The surface and the button that opens it were two unconnected nodes: the
|
|
57
57
|
// menu/dialog had no id, so nothing could point at it, and no accessible
|
|
58
58
|
// name, so a screen reader announced a bare "menu"/"dialog". Labelling the
|
|
@@ -68,6 +68,7 @@ function Menu({ trigger, children, align = "start", open: openProp, defaultOpen,
|
|
|
68
68
|
onOpenChange?.(next);
|
|
69
69
|
}, [openProp, onOpenChange]);
|
|
70
70
|
const [up, setUp] = React.useState(false);
|
|
71
|
+
const [submenuAlign, setSubmenuAlign] = React.useState("start");
|
|
71
72
|
const [pos, setPos] = React.useState({});
|
|
72
73
|
const rootRef = React.useRef(null);
|
|
73
74
|
const triggerRef = React.useRef(null);
|
|
@@ -79,6 +80,38 @@ function Menu({ trigger, children, align = "start", open: openProp, defaultOpen,
|
|
|
79
80
|
const rect = triggerRef.current?.getBoundingClientRect();
|
|
80
81
|
if (!rect)
|
|
81
82
|
return;
|
|
83
|
+
if (placement === "submenu") {
|
|
84
|
+
// The content div is already in the DOM by this point (it's part of
|
|
85
|
+
// the same render this effect runs after, just not yet painted) so its
|
|
86
|
+
// real rendered size/padding are measurable, not guessed.
|
|
87
|
+
const content = contentRef.current;
|
|
88
|
+
const size = content?.getBoundingClientRect() ?? {
|
|
89
|
+
width: 200,
|
|
90
|
+
height: 0,
|
|
91
|
+
};
|
|
92
|
+
const padTop = content
|
|
93
|
+
? Number.parseFloat(getComputedStyle(content).paddingTop) || 0
|
|
94
|
+
: 0;
|
|
95
|
+
const { style, align: side, up: flipUp, } = (0, core_1.placeSubmenu)({
|
|
96
|
+
// Not a `{...rect}` spread: DOMRect's numeric fields are accessors
|
|
97
|
+
// on its prototype, not own enumerable properties, so a spread
|
|
98
|
+
// silently drops everything except the two overridden below.
|
|
99
|
+
rect: {
|
|
100
|
+
left: rect.left,
|
|
101
|
+
right: rect.right,
|
|
102
|
+
top: rect.top - padTop,
|
|
103
|
+
bottom: rect.bottom - padTop,
|
|
104
|
+
},
|
|
105
|
+
size,
|
|
106
|
+
// Measured flush against the item, no gap (crisp#616).
|
|
107
|
+
gap: 0,
|
|
108
|
+
anchor: triggerRef.current,
|
|
109
|
+
});
|
|
110
|
+
setSubmenuAlign(side);
|
|
111
|
+
setUp(flipUp);
|
|
112
|
+
setPos(style);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
82
115
|
const { style, up: flipUp } = (0, core_1.placeFloating)({
|
|
83
116
|
rect,
|
|
84
117
|
align,
|
|
@@ -181,18 +214,25 @@ function Menu({ trigger, children, align = "start", open: openProp, defaultOpen,
|
|
|
181
214
|
});
|
|
182
215
|
return ((0, jsx_runtime_1.jsxs)("div", { ref: rootRef, className: (0, menu_recipe_1.menuRecipe)({ className }), children: [triggerEl, open && ((0, jsx_runtime_1.jsx)(core_1.FloatingPortal, { sourceRef: rootRef, children: (0, jsx_runtime_1.jsx)("div", { ref: contentRef, className: contentClassName
|
|
183
216
|
? `crisp-menu-content ${contentClassName}`
|
|
184
|
-
: "crisp-menu-content", role: "menu", id: surfaceId, "aria-label": ariaLabel, "aria-labelledby": ariaLabel ? undefined : triggerId, "data-align": align, "data-up": up ? "" : undefined, style: pos, onKeyDown: onContentKeyDown, onFocus: onContentFocus, children: (0, jsx_runtime_1.jsx)(MenuContext.Provider, { value: { close }, children: children }) }) }))] }));
|
|
217
|
+
: "crisp-menu-content", role: "menu", id: surfaceId, "aria-label": ariaLabel, "aria-labelledby": ariaLabel ? undefined : triggerId, "data-align": placement === "submenu" ? submenuAlign : align, "data-up": up ? "" : undefined, style: pos, onKeyDown: onContentKeyDown, onFocus: onContentFocus, children: (0, jsx_runtime_1.jsx)(MenuContext.Provider, { value: { close }, children: children }) }) }))] }));
|
|
185
218
|
}
|
|
186
219
|
Menu.displayName = "Menu";
|
|
187
|
-
|
|
220
|
+
/**
|
|
221
|
+
* A row inside a `Menu`. Forwards its ref and spreads unrecognised button
|
|
222
|
+
* props (crisp#616) so it can double as another `Menu`'s own `trigger` —
|
|
223
|
+
* `Menu` clones its trigger with `ref`/`onClick`/`aria-*`, which a plain
|
|
224
|
+
* function component would silently drop.
|
|
225
|
+
*/
|
|
226
|
+
exports.MenuItem = React.forwardRef(function MenuItem({ children, icon, shortcut, count, trailingIcon, danger, disabled, onSelect, closeOnSelect = true, onClick, ...rest }, ref) {
|
|
188
227
|
const ctx = React.useContext(MenuContext);
|
|
189
|
-
return ((0, jsx_runtime_1.jsxs)("button", { type: "button", role: "menuitem", tabIndex: -1, disabled: disabled, "data-disabled": disabled ? "" : undefined, className: `crisp-menu-item${danger ? " crisp-menu-item--danger" : ""}`, onClick: () => {
|
|
228
|
+
return ((0, jsx_runtime_1.jsxs)("button", { ref: ref, type: "button", role: "menuitem", tabIndex: -1, disabled: disabled, "data-disabled": disabled ? "" : undefined, className: `crisp-menu-item${danger ? " crisp-menu-item--danger" : ""}`, onClick: (e) => {
|
|
229
|
+
onClick?.(e);
|
|
190
230
|
onSelect?.();
|
|
191
231
|
if (closeOnSelect)
|
|
192
232
|
ctx?.close();
|
|
193
|
-
}, children: [icon, (0, jsx_runtime_1.jsx)("span", { className: "crisp-menu-item-label", children: children }), count != null && (0, jsx_runtime_1.jsx)("span", { className: "crisp-menu-item-count", children: count }), shortcut && (0, jsx_runtime_1.jsx)("span", { className: "crisp-menu-item-shortcut", children: shortcut })] }));
|
|
194
|
-
}
|
|
195
|
-
MenuItem.displayName = "MenuItem";
|
|
233
|
+
}, ...rest, children: [icon, (0, jsx_runtime_1.jsx)("span", { className: "crisp-menu-item-label", children: children }), count != null && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-menu-item-count", children: count })), shortcut && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-menu-item-shortcut", children: shortcut })), trailingIcon] }));
|
|
234
|
+
});
|
|
235
|
+
exports.MenuItem.displayName = "MenuItem";
|
|
196
236
|
function MenuCheckboxItem({ children, checked, onCheckedChange, disabled, }) {
|
|
197
237
|
return ((0, jsx_runtime_1.jsxs)("button", { type: "button", role: "menuitemcheckbox", "aria-checked": checked, tabIndex: -1, disabled: disabled, "data-disabled": disabled ? "" : undefined, className: "crisp-menu-item", onClick: () => onCheckedChange?.(!checked), children: [checked ? ((0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "crisp-menu-item-check", size: 15, strokeWidth: 2 })) : ((0, jsx_runtime_1.jsx)("span", { className: "crisp-menu-item-check--placeholder" })), (0, jsx_runtime_1.jsx)("span", { className: "crisp-menu-item-label", children: children })] }));
|
|
198
238
|
}
|
|
@@ -57,6 +57,9 @@ function toneFor(t) {
|
|
|
57
57
|
return TONES[h % TONES.length];
|
|
58
58
|
}
|
|
59
59
|
function Chip({ opt }) {
|
|
60
|
+
if (opt.swatch) {
|
|
61
|
+
return ((0, jsx_runtime_1.jsx)("span", { className: "crisp-multiselect-swatch", "data-swatch": opt.swatch, children: opt.label }));
|
|
62
|
+
}
|
|
60
63
|
return ((0, jsx_runtime_1.jsx)("span", { className: "crisp-recordstable-tag", "data-tone": opt.tone ?? toneFor(opt.value), children: opt.label }));
|
|
61
64
|
}
|
|
62
65
|
/**
|
|
@@ -107,6 +107,24 @@ const config = (0, core_1.defineRecipe)({
|
|
|
107
107
|
.crisp-recordstable-tag[data-tone="purple"] { background: color-mix(in srgb, ${tokens_1.contract.bgPurple} 16%, transparent); color: color-mix(in srgb, ${tokens_1.contract.bgPurple} 80%, ${tokens_1.contract.fgPrimary}); box-shadow: inset 0 0 0 1px color-mix(in srgb, ${tokens_1.contract.bgPurple} 30%, transparent); }
|
|
108
108
|
.crisp-recordstable-tag[data-tone="cyan"] { background: color-mix(in srgb, ${tokens_1.contract.bgCyan} 18%, transparent); color: color-mix(in srgb, ${tokens_1.contract.bgCyan} 82%, ${tokens_1.contract.fgPrimary}); box-shadow: inset 0 0 0 1px color-mix(in srgb, ${tokens_1.contract.bgCyan} 30%, transparent); }
|
|
109
109
|
.crisp-recordstable-tag[data-tone="orange"] { background: color-mix(in srgb, ${tokens_1.contract.bgOrange} 16%, transparent); color: color-mix(in srgb, ${tokens_1.contract.bgOrange} 82%, ${tokens_1.contract.fgPrimary}); box-shadow: inset 0 0 0 1px color-mix(in srgb, ${tokens_1.contract.bgOrange} 30%, transparent); }
|
|
110
|
+
/* your-moon/crisp#998: Attio's own 12-colour tag palette (measured live,
|
|
111
|
+
see tokens/palette.ts's tagSwatch1 comment) -- flat black text, no
|
|
112
|
+
ring/border, unlike the tone family above. 7px radius/10px text are
|
|
113
|
+
measured literals, no matching step in the shared scale (same as
|
|
114
|
+
Select's own .crisp-select-swatch). */
|
|
115
|
+
.crisp-multiselect-swatch { display: inline-flex; align-items: center; height: ${tokens_1.contract.size.chip}; padding: 0 ${tokens_1.contract.space["1"]}; border-radius: 7px; font-size: 10px; font-weight: ${tokens_1.contract.weight.regular}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: ${tokens_1.contract.fgTagSwatch}; }
|
|
116
|
+
.crisp-multiselect-swatch[data-swatch="1"] { background: ${tokens_1.contract.bgTagSwatch1}; }
|
|
117
|
+
.crisp-multiselect-swatch[data-swatch="2"] { background: ${tokens_1.contract.bgTagSwatch2}; }
|
|
118
|
+
.crisp-multiselect-swatch[data-swatch="3"] { background: ${tokens_1.contract.bgTagSwatch3}; }
|
|
119
|
+
.crisp-multiselect-swatch[data-swatch="4"] { background: ${tokens_1.contract.bgTagSwatch4}; }
|
|
120
|
+
.crisp-multiselect-swatch[data-swatch="5"] { background: ${tokens_1.contract.bgTagSwatch5}; }
|
|
121
|
+
.crisp-multiselect-swatch[data-swatch="6"] { background: ${tokens_1.contract.bgTagSwatch6}; }
|
|
122
|
+
.crisp-multiselect-swatch[data-swatch="7"] { background: ${tokens_1.contract.bgTagSwatch7}; }
|
|
123
|
+
.crisp-multiselect-swatch[data-swatch="8"] { background: ${tokens_1.contract.bgTagSwatch8}; }
|
|
124
|
+
.crisp-multiselect-swatch[data-swatch="9"] { background: ${tokens_1.contract.bgTagSwatch9}; }
|
|
125
|
+
.crisp-multiselect-swatch[data-swatch="10"] { background: ${tokens_1.contract.bgTagSwatch10}; }
|
|
126
|
+
.crisp-multiselect-swatch[data-swatch="11"] { background: ${tokens_1.contract.bgTagSwatch11}; }
|
|
127
|
+
.crisp-multiselect-swatch[data-swatch="12"] { background: ${tokens_1.contract.bgTagSwatch12}; }
|
|
110
128
|
`,
|
|
111
129
|
variants: {
|
|
112
130
|
// Owner's follow-up after #867/#879/#882 (crisp/#889): SIZE is Attio's
|
|
@@ -217,7 +217,7 @@ function Select({ options, value, defaultValue, onValueChange, name, required, p
|
|
|
217
217
|
return ((0, jsx_runtime_1.jsxs)("div", { ref: rootRef, className: (0, select_recipe_1.selectRecipe)({ variant, width, size, invalid, className }), ...rest, children: [name && (selected || required) && ((0, jsx_runtime_1.jsx)("input", { className: "crisp-formvalue", style: core_1.formValueStyle, name: name, value: selected ?? "", required: required, tabIndex: -1, "aria-hidden": "true",
|
|
218
218
|
// controlled by the listbox above; `readOnly` would bar it from
|
|
219
219
|
// validation, which is the only reason this input is not hidden
|
|
220
|
-
onChange: () => { } })), (0, jsx_runtime_1.jsxs)("button", { ref: triggerRef, type: "button", id: id, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": open ? listboxId : undefined, "aria-activedescendant": searchable ? undefined : activeId, "aria-label": ariaLabel, "aria-invalid": invalid === true || undefined, "aria-readonly": readOnly ? "true" : undefined, disabled: disabled, "data-open": open ? "" : undefined, className: "crisp-select-trigger", onClick: () => (open ? setOpen(false) : openMenu()), onKeyDown: onTriggerKeyDown, children: [(0, jsx_runtime_1.jsx)("span", { className: "crisp-select-value", children: selectedOption ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [selectedOption.color && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-select-option-dot", style: { background: selectedOption.color } })), selectedOption.triggerLabel ?? selectedOption.label] })) : ((0, jsx_runtime_1.jsx)("span", { className: "crisp-select-placeholder", children: placeholder })) }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { className: "crisp-select-chevron", size: 16, strokeWidth: 1.75 })] }), open && ((0, jsx_runtime_1.jsx)(core_1.FloatingPortal, { sourceRef: rootRef, children: (0, jsx_runtime_1.jsxs)("div", { ref: listboxRef, id: listboxId, className: "crisp-select-listbox", role: "listbox", "aria-label": ariaLabel, "data-up": up ? "" : undefined, style: pos, children: [searchable && ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-select-search", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Search, { size: 16, strokeWidth: 1.75 }), (0, jsx_runtime_1.jsx)("input", { ref: searchRef, type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, "aria-controls": listboxId, "aria-activedescendant": activeId, value: query, onChange: (e) => {
|
|
220
|
+
onChange: () => { } })), (0, jsx_runtime_1.jsxs)("button", { ref: triggerRef, type: "button", id: id, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": open ? listboxId : undefined, "aria-activedescendant": searchable ? undefined : activeId, "aria-label": ariaLabel, "aria-invalid": invalid === true || undefined, "aria-readonly": readOnly ? "true" : undefined, disabled: disabled, "data-open": open ? "" : undefined, className: "crisp-select-trigger", onClick: () => (open ? setOpen(false) : openMenu()), onKeyDown: onTriggerKeyDown, children: [(0, jsx_runtime_1.jsx)("span", { className: "crisp-select-value", children: selectedOption ? (selectedOption.swatch ? ((0, jsx_runtime_1.jsx)("span", { className: "crisp-select-swatch", "data-swatch": selectedOption.swatch, children: selectedOption.triggerLabel ?? selectedOption.label })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [selectedOption.color && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-select-option-dot", style: { background: selectedOption.color } })), selectedOption.triggerLabel ?? selectedOption.label] }))) : ((0, jsx_runtime_1.jsx)("span", { className: "crisp-select-placeholder", children: placeholder })) }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { className: "crisp-select-chevron", size: 16, strokeWidth: 1.75 })] }), open && ((0, jsx_runtime_1.jsx)(core_1.FloatingPortal, { sourceRef: rootRef, children: (0, jsx_runtime_1.jsxs)("div", { ref: listboxRef, id: listboxId, className: "crisp-select-listbox", role: "listbox", "aria-label": ariaLabel, "data-up": up ? "" : undefined, style: pos, children: [searchable && ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-select-search", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Search, { size: 16, strokeWidth: 1.75 }), (0, jsx_runtime_1.jsx)("input", { ref: searchRef, type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, "aria-controls": listboxId, "aria-activedescendant": activeId, value: query, onChange: (e) => {
|
|
221
221
|
setQuery(e.target.value);
|
|
222
222
|
setHighlight(0);
|
|
223
223
|
onSearchChange?.(e.target.value);
|
|
@@ -228,7 +228,7 @@ function Select({ options, value, defaultValue, onValueChange, name, required, p
|
|
|
228
228
|
// heading, not one each.
|
|
229
229
|
const showGroupLabel = opt.group !== undefined &&
|
|
230
230
|
opt.group !== filtered[i - 1]?.group;
|
|
231
|
-
return ((0, jsx_runtime_1.jsxs)(React.Fragment, { children: [showGroupLabel && ((0, jsx_runtime_1.jsx)("div", { className: "crisp-select-label", children: opt.group })), (0, jsx_runtime_1.jsxs)("button", { type: "button", id: optionId(i), role: "option", "aria-selected": isSel, tabIndex: -1, disabled: opt.disabled, "data-disabled": opt.disabled ? "" : undefined, "data-highlighted": i === highlight ? "" : undefined, className: "crisp-select-option", onClick: () => pick(opt), onMouseEnter: () => setHighlight(i), children: [opt.color && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-select-option-dot", style: { background: opt.color } })), opt.description !== undefined ? ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-select-option-body", children: [(0, jsx_runtime_1.jsx)("span", { className: "crisp-select-option-label", children: opt.label }), (0, jsx_runtime_1.jsx)("span", { className: "crisp-select-option-description", children: opt.description })] })) : ((0, jsx_runtime_1.jsx)("span", { className: "crisp-select-option-label", children: opt.label })), isSel && ((0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "crisp-select-option-check", size: 15, strokeWidth: 2 }))] })] }, opt.value));
|
|
231
|
+
return ((0, jsx_runtime_1.jsxs)(React.Fragment, { children: [showGroupLabel && ((0, jsx_runtime_1.jsx)("div", { className: "crisp-select-label", children: opt.group })), (0, jsx_runtime_1.jsxs)("button", { type: "button", id: optionId(i), role: "option", "aria-selected": isSel, tabIndex: -1, disabled: opt.disabled, "data-disabled": opt.disabled ? "" : undefined, "data-highlighted": i === highlight ? "" : undefined, className: "crisp-select-option", onClick: () => pick(opt), onMouseEnter: () => setHighlight(i), children: [!opt.swatch && opt.color && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-select-option-dot", style: { background: opt.color } })), opt.description !== undefined ? ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-select-option-body", children: [(0, jsx_runtime_1.jsx)("span", { className: "crisp-select-option-label", children: opt.swatch ? ((0, jsx_runtime_1.jsx)("span", { className: "crisp-select-swatch", "data-swatch": opt.swatch, children: opt.label })) : (opt.label) }), (0, jsx_runtime_1.jsx)("span", { className: "crisp-select-option-description", children: opt.description })] })) : ((0, jsx_runtime_1.jsx)("span", { className: "crisp-select-option-label", children: opt.swatch ? ((0, jsx_runtime_1.jsx)("span", { className: "crisp-select-swatch", "data-swatch": opt.swatch, children: opt.label })) : (opt.label) })), isSel && ((0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "crisp-select-option-check", size: 15, strokeWidth: 2 }))] })] }, opt.value));
|
|
232
232
|
}))] }) }))] }));
|
|
233
233
|
}
|
|
234
234
|
Select.displayName = "Select";
|
|
@@ -137,6 +137,25 @@ const config = (0, core_1.defineRecipe)({
|
|
|
137
137
|
.crisp-select-option[data-disabled] .crisp-select-option-description,
|
|
138
138
|
.crisp-select-option[data-disabled] .crisp-select-option-check { color: ${tokens_1.contract.fgDisabled}; }
|
|
139
139
|
.crisp-select-option-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: ${tokens_1.contract.radius.full}; margin-inline-end: ${tokens_1.contract.space["2"]}; }
|
|
140
|
+
/* your-moon/crisp#998: Attio's own 12-colour tag palette (measured live,
|
|
141
|
+
see tokens/palette.ts's tagSwatch1 comment) -- the label itself as a
|
|
142
|
+
filled pill, not a dot beside it. 7px radius/10px text have no
|
|
143
|
+
matching step in the shared scale (radius.xs is 4px, .sm is 6px;
|
|
144
|
+
text.xs is 11px), so both are the measured literals, same as
|
|
145
|
+
DataTable's own avatar font-size (#891). */
|
|
146
|
+
.crisp-select-swatch { display: inline-flex; align-items: center; height: ${tokens_1.contract.size.chip}; padding: 0 ${tokens_1.contract.space["1"]}; border-radius: 7px; font-size: 10px; font-weight: ${tokens_1.contract.weight.regular}; color: ${tokens_1.contract.fgTagSwatch}; }
|
|
147
|
+
.crisp-select-swatch[data-swatch="1"] { background: ${tokens_1.contract.bgTagSwatch1}; }
|
|
148
|
+
.crisp-select-swatch[data-swatch="2"] { background: ${tokens_1.contract.bgTagSwatch2}; }
|
|
149
|
+
.crisp-select-swatch[data-swatch="3"] { background: ${tokens_1.contract.bgTagSwatch3}; }
|
|
150
|
+
.crisp-select-swatch[data-swatch="4"] { background: ${tokens_1.contract.bgTagSwatch4}; }
|
|
151
|
+
.crisp-select-swatch[data-swatch="5"] { background: ${tokens_1.contract.bgTagSwatch5}; }
|
|
152
|
+
.crisp-select-swatch[data-swatch="6"] { background: ${tokens_1.contract.bgTagSwatch6}; }
|
|
153
|
+
.crisp-select-swatch[data-swatch="7"] { background: ${tokens_1.contract.bgTagSwatch7}; }
|
|
154
|
+
.crisp-select-swatch[data-swatch="8"] { background: ${tokens_1.contract.bgTagSwatch8}; }
|
|
155
|
+
.crisp-select-swatch[data-swatch="9"] { background: ${tokens_1.contract.bgTagSwatch9}; }
|
|
156
|
+
.crisp-select-swatch[data-swatch="10"] { background: ${tokens_1.contract.bgTagSwatch10}; }
|
|
157
|
+
.crisp-select-swatch[data-swatch="11"] { background: ${tokens_1.contract.bgTagSwatch11}; }
|
|
158
|
+
.crisp-select-swatch[data-swatch="12"] { background: ${tokens_1.contract.bgTagSwatch12}; }
|
|
140
159
|
.crisp-select-option-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: ${tokens_1.contract.space["0.5"]}; }
|
|
141
160
|
.crisp-select-option-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
142
161
|
.crisp-select-option-description { min-width: 0; overflow: hidden; text-overflow: ellipsis; color: ${tokens_1.contract.fgNeutralSubtle}; }
|
package/dist/cjs/core/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.usePrefersReducedMotion = exports.useMentionTrigger = exports.useLabelAssociation = exports.useFormReset = exports.useFocusAfterRemoval = exports.specToRecipe = exports.defineSpec = exports.resolveRecipe = exports.Primitive = exports.placeFloating = exports.matchMentionTrigger = exports.useCrispMessages = exports.useCrispMessage = exports.useCrispComponentDefaults = exports.CrispMessagesProvider = exports.formValueStyle = exports.registerFloatingLayer = exports.isInsideLaterFloatingLayer = exports.hasOpenFloatingLayer = exports.hasNestedFloatingLayer = exports.FloatingPortal = exports.isRtlElement = exports.withDescribedBy = exports.defineRecipe = exports.cx = exports.parseCellDate = exports.formatCellDate = exports.cellDatePrecision = exports.caretRectInField = void 0;
|
|
17
|
+
exports.usePrefersReducedMotion = exports.useMentionTrigger = exports.useLabelAssociation = exports.useFormReset = exports.useFocusAfterRemoval = exports.specToRecipe = exports.defineSpec = exports.resolveRecipe = exports.Primitive = exports.placeSubmenu = exports.placeFloating = exports.matchMentionTrigger = exports.useCrispMessages = exports.useCrispMessage = exports.useCrispComponentDefaults = exports.CrispMessagesProvider = exports.formValueStyle = exports.registerFloatingLayer = exports.isInsideLaterFloatingLayer = exports.hasOpenFloatingLayer = exports.hasNestedFloatingLayer = exports.FloatingPortal = exports.isRtlElement = exports.withDescribedBy = exports.defineRecipe = exports.cx = exports.parseCellDate = exports.formatCellDate = exports.cellDatePrecision = exports.caretRectInField = void 0;
|
|
18
18
|
var caret_rect_1 = require("./caret-rect");
|
|
19
19
|
Object.defineProperty(exports, "caretRectInField", { enumerable: true, get: function () { return caret_rect_1.caretRectInField; } });
|
|
20
20
|
var cell_date_1 = require("./cell-date");
|
|
@@ -47,6 +47,7 @@ var mention_1 = require("./mention");
|
|
|
47
47
|
Object.defineProperty(exports, "matchMentionTrigger", { enumerable: true, get: function () { return mention_1.matchMentionTrigger; } });
|
|
48
48
|
var place_floating_1 = require("./place-floating");
|
|
49
49
|
Object.defineProperty(exports, "placeFloating", { enumerable: true, get: function () { return place_floating_1.placeFloating; } });
|
|
50
|
+
Object.defineProperty(exports, "placeSubmenu", { enumerable: true, get: function () { return place_floating_1.placeSubmenu; } });
|
|
50
51
|
var primitive_1 = require("./primitive");
|
|
51
52
|
Object.defineProperty(exports, "Primitive", { enumerable: true, get: function () { return primitive_1.Primitive; } });
|
|
52
53
|
var resolve_1 = require("./resolve");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.placeFloating = placeFloating;
|
|
4
|
+
exports.placeSubmenu = placeSubmenu;
|
|
4
5
|
const direction_1 = require("./direction");
|
|
5
6
|
/**
|
|
6
7
|
* Where a floating layer goes, in logical terms.
|
|
@@ -36,3 +37,40 @@ function placeFloating({ rect, align = "start", gap, flipBelow, anchor, }) {
|
|
|
36
37
|
style.left = rect.left;
|
|
37
38
|
return { style, up };
|
|
38
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Where a cascading submenu goes, BESIDE the item that opens it — not below
|
|
42
|
+
* it, the way `placeFloating`'s own dropdown does. Opens toward the inline
|
|
43
|
+
* end by default (further into the reading direction) and flips to the
|
|
44
|
+
* inline start when the surface's measured width doesn't fit there.
|
|
45
|
+
*
|
|
46
|
+
* Live-measured on Attio's own object-page "…" menu (crisp#616): the
|
|
47
|
+
* Notifications submenu sits with NO gap against the item's opposite edge
|
|
48
|
+
* (its own edge lines up exactly with the item's), so callers pass `gap: 0`
|
|
49
|
+
* for this specific cascade rather than the 4px a dropdown uses against its
|
|
50
|
+
* trigger.
|
|
51
|
+
*/
|
|
52
|
+
function placeSubmenu({ rect, size, gap, anchor, }) {
|
|
53
|
+
const rtl = (0, direction_1.isRtlElement)(anchor);
|
|
54
|
+
// "end" here is the inline-end direction FROM the item, e.g. further
|
|
55
|
+
// right in LTR — the room available there is measured from whichever
|
|
56
|
+
// physical edge that is.
|
|
57
|
+
const roomTowardEnd = rtl ? rect.left : window.innerWidth - rect.right;
|
|
58
|
+
const opensEnd = roomTowardEnd >= size.width + gap;
|
|
59
|
+
const align = opensEnd ? "start" : "end";
|
|
60
|
+
const style = {};
|
|
61
|
+
// Same formula as `placeFloating`'s own `toRight`, applied to the opposite
|
|
62
|
+
// geometry: there `align` picks which of the TRIGGER's edges the layer's
|
|
63
|
+
// matching edge lines up with; here it picks which side of the ITEM the
|
|
64
|
+
// layer cascades toward.
|
|
65
|
+
const anchorRight = align === "end" ? !rtl : rtl;
|
|
66
|
+
if (anchorRight)
|
|
67
|
+
style.right = window.innerWidth - rect.left + gap;
|
|
68
|
+
else
|
|
69
|
+
style.left = rect.right + gap;
|
|
70
|
+
const up = rect.top + size.height > window.innerHeight;
|
|
71
|
+
if (up)
|
|
72
|
+
style.bottom = Math.max(0, window.innerHeight - rect.bottom);
|
|
73
|
+
else
|
|
74
|
+
style.top = rect.top;
|
|
75
|
+
return { style, align, up };
|
|
76
|
+
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -92,6 +92,7 @@ __exportStar(require("./core"), exports);
|
|
|
92
92
|
// the generic primitives (Table, DataTable, Button, …) to build your own UI from.
|
|
93
93
|
__exportStar(require("./product/activityfeed"), exports);
|
|
94
94
|
__exportStar(require("./product/appshell"), exports);
|
|
95
|
+
__exportStar(require("./product/assigneepicker"), exports);
|
|
95
96
|
__exportStar(require("./product/authshell"), exports);
|
|
96
97
|
__exportStar(require("./product/board"), exports);
|
|
97
98
|
__exportStar(require("./product/command"), exports);
|
|
@@ -105,21 +106,28 @@ __exportStar(require("./product/inbox"), exports);
|
|
|
105
106
|
__exportStar(require("./product/listpage"), exports);
|
|
106
107
|
__exportStar(require("./product/memberssettings"), exports);
|
|
107
108
|
__exportStar(require("./product/navitem"), exports);
|
|
109
|
+
__exportStar(require("./product/notesgallery"), exports);
|
|
108
110
|
__exportStar(require("./product/notificationssettings"), exports);
|
|
111
|
+
__exportStar(require("./product/objectpagemenu"), exports);
|
|
109
112
|
__exportStar(require("./product/objectsettings"), exports);
|
|
110
113
|
__exportStar(require("./product/onboarding"), exports);
|
|
111
114
|
__exportStar(require("./product/recordpage"), exports);
|
|
112
115
|
__exportStar(require("./product/recordpanel"), exports);
|
|
116
|
+
__exportStar(require("./product/recordpicker"), exports);
|
|
113
117
|
__exportStar(require("./product/richtext"), exports);
|
|
114
118
|
__exportStar(require("./product/savedviews"), exports);
|
|
115
119
|
__exportStar(require("./product/settingssection"), exports);
|
|
116
120
|
__exportStar(require("./product/settingsshell"), exports);
|
|
121
|
+
__exportStar(require("./product/share"), exports);
|
|
122
|
+
__exportStar(require("./product/shortcutssheet"), exports);
|
|
117
123
|
__exportStar(require("./product/sidebar"), exports);
|
|
118
124
|
__exportStar(require("./product/statlist"), exports);
|
|
125
|
+
__exportStar(require("./product/taskeditpopover"), exports);
|
|
119
126
|
__exportStar(require("./product/tasklist"), exports);
|
|
120
127
|
__exportStar(require("./product/themepicker"), exports);
|
|
121
128
|
__exportStar(require("./product/trialbanner"), exports);
|
|
122
129
|
__exportStar(require("./product/viewtoggle"), exports);
|
|
123
130
|
__exportStar(require("./product/workspacegeneralsettings"), exports);
|
|
131
|
+
__exportStar(require("./product/workspaceswitchermenu"), exports);
|
|
124
132
|
// design tokens + recipe core (for building custom components)
|
|
125
133
|
__exportStar(require("./tokens"), exports);
|