@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.
- package/dist/assigneepicker.css +13 -0
- package/dist/assigneepicker.d.ts +7 -0
- package/dist/assigneepicker.layered.css +15 -0
- package/dist/button.css +3 -0
- package/dist/button.d.ts +2 -2
- package/dist/button.layered.css +3 -0
- package/dist/chip.css +1 -1
- package/dist/chip.layered.css +1 -1
- package/dist/cjs/components/breadcrumb/breadcrumb.js +1 -1
- package/dist/cjs/components/button/button.recipe.js +33 -0
- package/dist/cjs/components/chip/chip.recipe.js +3 -1
- package/dist/cjs/components/datatable/datatable.js +6 -3
- package/dist/cjs/components/datatable/datatable.recipe.js +45 -6
- package/dist/cjs/components/datepickerfield/datepickerfield.js +2 -2
- package/dist/cjs/components/datepickerfield/datepickerfield.recipe.js +16 -3
- package/dist/cjs/components/menu/menu.js +65 -9
- 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/components/table/table.recipe.js +7 -1
- package/dist/cjs/core/floating-portal.js +7 -4
- 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/inbox/inbox.js +11 -3
- 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/index.js +2 -1
- package/dist/cjs/product/recordpage/recordpage.js +112 -7
- package/dist/cjs/product/recordpage/recordpage.recipe.js +63 -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 +50 -11
- package/dist/datatable.layered.css +50 -11
- package/dist/datepickerfield.css +8 -2
- package/dist/datepickerfield.d.ts +2 -2
- package/dist/datepickerfield.layered.css +8 -2
- package/dist/esm/components/breadcrumb/breadcrumb.js +1 -1
- package/dist/esm/components/button/button.recipe.js +33 -0
- package/dist/esm/components/chip/chip.recipe.js +3 -1
- package/dist/esm/components/datatable/datatable.js +6 -3
- package/dist/esm/components/datatable/datatable.recipe.js +45 -6
- package/dist/esm/components/datepickerfield/datepickerfield.js +2 -2
- package/dist/esm/components/datepickerfield/datepickerfield.recipe.js +16 -3
- package/dist/esm/components/menu/menu.js +64 -8
- 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/components/table/table.recipe.js +7 -1
- package/dist/esm/core/floating-portal.js +7 -4
- 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/inbox/inbox.js +11 -3
- 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/index.js +1 -1
- package/dist/esm/product/recordpage/recordpage.js +112 -8
- package/dist/esm/product/recordpage/recordpage.recipe.js +63 -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 +59 -0
- package/dist/recordpage.layered.css +59 -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 +438 -16
- package/dist/styles.layered.css +438 -16
- package/dist/table.css +7 -2
- package/dist/table.layered.css +7 -2
- 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/breadcrumb/breadcrumb.d.ts +9 -1
- package/dist/types/components/button/button.d.ts +2 -0
- package/dist/types/components/button/button.recipe.d.ts +12 -0
- package/dist/types/components/chip/chip.recipe.d.ts +1 -1
- package/dist/types/components/datatable/datatable.d.ts +8 -0
- package/dist/types/components/datepickerfield/datepickerfield.d.ts +4 -1
- package/dist/types/components/datepickerfield/datepickerfield.recipe.d.ts +18 -3
- 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/floating-portal.d.ts +6 -5
- 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/inbox/inbox.d.ts +13 -1
- 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 +142 -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
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
.crisp-button--size_sm {
|
|
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
|
+
.crisp-button--size_xs {
|
|
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
|
+
}
|
|
27
30
|
.crisp-button--size_md {
|
|
28
31
|
height: 28px; padding-inline: var(--crisp-space-2); font-size: var(--crisp-text-lg); border-radius: var(--crisp-radius-md);
|
|
29
32
|
&[data-icon-start] { padding-inline-start: var(--crisp-space-1-5); }
|
package/dist/button.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ import type { RecipeFn } from "../core/types";
|
|
|
2
2
|
|
|
3
3
|
export interface ButtonVariants {
|
|
4
4
|
intent?: "primary" | "neutral" | "danger" | "ghost";
|
|
5
|
-
size?: "sm" | "md" | "lg";
|
|
5
|
+
size?: "sm" | "xs" | "md" | "lg";
|
|
6
6
|
shape?: "text" | "icon";
|
|
7
7
|
touchTarget?: boolean;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export declare const buttonRecipe: RecipeFn<{ intent: { primary: string; neutral: string; danger: string; ghost: string }; size: { sm: string; md: string; lg: string }; shape: { text: string; icon: string }; touchTarget: { true: string; false: string } }>;
|
|
10
|
+
export declare const buttonRecipe: RecipeFn<{ intent: { primary: string; neutral: string; danger: string; ghost: string }; size: { sm: string; xs: string; md: string; lg: string }; shape: { text: string; icon: string }; touchTarget: { true: string; false: string } }>;
|
package/dist/button.layered.css
CHANGED
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
.crisp-button--size_sm {
|
|
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
|
+
.crisp-button--size_xs {
|
|
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
|
+
}
|
|
28
31
|
.crisp-button--size_md {
|
|
29
32
|
height: 28px; padding-inline: var(--crisp-space-2); font-size: var(--crisp-text-lg); border-radius: var(--crisp-radius-md);
|
|
30
33
|
&[data-icon-start] { padding-inline-start: var(--crisp-space-1-5); }
|
package/dist/chip.css
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
display: inline-flex; align-items: center; gap: 3px; height: var(--crisp-size-chip); min-width: 0; max-width: 100%; padding-inline: var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap;
|
|
3
3
|
}
|
|
4
4
|
.crisp-chip--truncate_true {
|
|
5
|
-
& .crisp-chip-label { min-width: 0; overflow:
|
|
5
|
+
& .crisp-chip-label { min-width: 0; overflow: clip; text-overflow: ellipsis; white-space: nowrap; display: block; }
|
|
6
6
|
}
|
|
7
7
|
.crisp-chip--truncate_false {
|
|
8
8
|
|
package/dist/chip.layered.css
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
display: inline-flex; align-items: center; gap: 3px; height: var(--crisp-size-chip); min-width: 0; max-width: 100%; padding-inline: var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap;
|
|
4
4
|
}
|
|
5
5
|
.crisp-chip--truncate_true {
|
|
6
|
-
& .crisp-chip-label { min-width: 0; overflow:
|
|
6
|
+
& .crisp-chip-label { min-width: 0; overflow: clip; text-overflow: ellipsis; white-space: nowrap; display: block; }
|
|
7
7
|
}
|
|
8
8
|
.crisp-chip--truncate_false {
|
|
9
9
|
|
|
@@ -55,7 +55,7 @@ function Breadcrumb({ items, separator, "aria-label": ariaLabelProp, className,
|
|
|
55
55
|
return ((0, jsx_runtime_1.jsx)("nav", { "aria-label": ariaLabel, className: (0, breadcrumb_recipe_1.breadcrumbRecipe)({ className }), ...rest, children: items.map((item, i) => {
|
|
56
56
|
const last = i === items.length - 1;
|
|
57
57
|
const content = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [item.icon, item.label] }));
|
|
58
|
-
return ((0, jsx_runtime_1.jsxs)(React.Fragment, { children: [last ? ((0, jsx_runtime_1.jsx)("span", { className: "crisp-breadcrumb-item", "aria-current": "page", children: content })) : item.href ? ((0, jsx_runtime_1.jsx)("a", { className: "crisp-breadcrumb-item", href: item.href, children: content })) : ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-breadcrumb-item", onClick: item.onClick, children: content })), !last && (0, jsx_runtime_1.jsx)("span", { className: "crisp-breadcrumb-sep", children: sep })] }, i));
|
|
58
|
+
return ((0, jsx_runtime_1.jsxs)(React.Fragment, { children: [last ? ((0, jsx_runtime_1.jsx)("span", { className: "crisp-breadcrumb-item", "aria-current": "page", children: content })) : item.href ? ((0, jsx_runtime_1.jsx)("a", { className: "crisp-breadcrumb-item", href: item.href, onClick: item.onClick, children: content })) : ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-breadcrumb-item", onClick: item.onClick, children: content })), !last && (0, jsx_runtime_1.jsx)("span", { className: "crisp-breadcrumb-sep", children: sep })] }, i));
|
|
59
59
|
}) }));
|
|
60
60
|
}
|
|
61
61
|
Breadcrumb.displayName = "Breadcrumb";
|
|
@@ -124,6 +124,39 @@ const spec = (0, core_1.defineSpec)({
|
|
|
124
124
|
fontSize: tokens_1.contract.text.md,
|
|
125
125
|
borderRadius: tokens_1.contract.radius.md,
|
|
126
126
|
},
|
|
127
|
+
// crisp#688: Attio's own 20px small button, split out of #682 rather
|
|
128
|
+
// than redefining `sm` -- 72 existing `size="sm"` call sites (sidebar,
|
|
129
|
+
// comments, recordpage, workspacegeneralsettings, personchip,
|
|
130
|
+
// datatable) already rely on sm's 24px, unverified against `xs`'s own
|
|
131
|
+
// context. Box measured live on app.attio.com Home/Tasks ("View all",
|
|
132
|
+
// "Today, <date>", the date-stepper's Previous/Next-day icon
|
|
133
|
+
// buttons): 20px height, 6px radius, 6px inline padding on text
|
|
134
|
+
// buttons (a 20x20 icon-only button centers a 16px icon the same way
|
|
135
|
+
// shape="icon" already does for every other size, so it needs no
|
|
136
|
+
// extra rule), 4px gap between multiple children.
|
|
137
|
+
//
|
|
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.
|
|
151
|
+
xs: {
|
|
152
|
+
height: "20px",
|
|
153
|
+
paddingInline: tokens_1.contract.space["1.5"],
|
|
154
|
+
fontSize: tokens_1.contract.text.sm,
|
|
155
|
+
lineHeight: "16px",
|
|
156
|
+
letterSpacing: "normal",
|
|
157
|
+
borderRadius: tokens_1.contract.radius.sm,
|
|
158
|
+
gap: tokens_1.contract.space["1"],
|
|
159
|
+
},
|
|
127
160
|
md: {
|
|
128
161
|
decls: {
|
|
129
162
|
height: "28px",
|
|
@@ -76,7 +76,9 @@ const spec = (0, core_1.defineSpec)({
|
|
|
76
76
|
selector: "& .crisp-chip-label",
|
|
77
77
|
decls: {
|
|
78
78
|
minWidth: 0,
|
|
79
|
-
|
|
79
|
+
// #719: `clip`, not `hidden` -- immune to a programmatic
|
|
80
|
+
// `scrollLeft` assignment; renders the ellipsis identically.
|
|
81
|
+
overflow: "clip",
|
|
80
82
|
textOverflow: "ellipsis",
|
|
81
83
|
whiteSpace: "nowrap",
|
|
82
84
|
display: "block",
|
|
@@ -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": {
|
|
@@ -116,7 +116,13 @@ const config = (0, core_1.defineRecipe)({
|
|
|
116
116
|
& .crisp-datatable-group-count { margin-inline-start: ${tokens_1.contract.space["1.5"]}; color: ${tokens_1.contract.fgMuted}; font-variant-numeric: tabular-nums; }
|
|
117
117
|
& .crisp-datatable-th-rename { width: 100%; min-width: 0; height: ${tokens_1.contract.size.row}; margin: 0; padding: 0 ${tokens_1.contract.space["1"]}; border: none; border-radius: ${tokens_1.contract.radius.md}; background: ${tokens_1.contract.bgSurface}; box-shadow: inset 0 0 0 1px ${tokens_1.contract.bgBrandSolid}; font-family: inherit; font-size: ${tokens_1.contract.text.lg}; font-weight: ${tokens_1.contract.weight.medium}; color: ${tokens_1.contract.fgPrimary}; outline: none; }
|
|
118
118
|
& .crisp-datatable-th-rename:focus { box-shadow: inset 0 0 0 1px ${tokens_1.contract.bgBrandSolid}; }
|
|
119
|
-
|
|
119
|
+
/* #719: overflow: clip, not hidden, on every truncation rule below --
|
|
120
|
+
hidden still honours a programmatic scrollLeft assignment (found via
|
|
121
|
+
a screenshot tool that pans anything with scrollWidth > clientWidth),
|
|
122
|
+
blanking or fragmenting the visible text even though real user
|
|
123
|
+
scrolling was already blocked. clip renders the ellipsis identically
|
|
124
|
+
and leaves no scroll position to move. */
|
|
125
|
+
& .crisp-datatable-th-label { overflow: clip; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
120
126
|
/* #465: 12px per the comment above (and Attio's measured header cell
|
|
121
127
|
padding: 0 12px) -- was still c.space["2"] (8px), drifted from its
|
|
122
128
|
own documented value. */
|
|
@@ -203,7 +209,7 @@ const config = (0, core_1.defineRecipe)({
|
|
|
203
209
|
/* reference picker: a leading 16px avatar per option, plus a trailing
|
|
204
210
|
"Create X" row when the consumer supplies one (#449) -- same measured
|
|
205
211
|
values as RecordsTable's own .crisp-recordstable-refoption*. */
|
|
206
|
-
& .crisp-datatable-refoption { display: flex; align-items: center; gap: ${tokens_1.contract.space["2"]}; min-width: 0; overflow:
|
|
212
|
+
& .crisp-datatable-refoption { display: flex; align-items: center; gap: ${tokens_1.contract.space["2"]}; min-width: 0; overflow: clip; text-overflow: ellipsis; }
|
|
207
213
|
& .crisp-datatable-refoption-avatar { flex-shrink: 0; }
|
|
208
214
|
& .crisp-datatable-refoption--create { color: ${tokens_1.contract.fgMuted}; }
|
|
209
215
|
& .crisp-datatable-empty { padding: ${tokens_1.contract.space["8"]} ${tokens_1.contract.space["3"]}; text-align: center; color: ${tokens_1.contract.fgMuted}; font-size: ${tokens_1.contract.text.lg}; }
|
|
@@ -289,7 +295,7 @@ const config = (0, core_1.defineRecipe)({
|
|
|
289
295
|
(#833/#835/#848) that happened to apply the same 500 to every
|
|
290
296
|
primary-column body cell regardless of type. Made explicit here so
|
|
291
297
|
fixing that leak doesn't also (wrongly) drop entity names to 400. */
|
|
292
|
-
& .crisp-datatable-entity-name { overflow:
|
|
298
|
+
& .crisp-datatable-entity-name { overflow: clip; text-overflow: ellipsis; white-space: nowrap; font-weight: ${tokens_1.contract.weight.medium}; text-decoration: underline; text-decoration-color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 9%, transparent); }
|
|
293
299
|
/* #893: shared by the button (onEntityClick, a different record) and
|
|
294
300
|
the anchor (href, the row's own record) -- was button-only, which
|
|
295
301
|
silently left a real <a> unstyled the day #893 added one. */
|
|
@@ -312,9 +318,24 @@ const config = (0, core_1.defineRecipe)({
|
|
|
312
318
|
Avatar's own already-shipped shape="rounded" value, not a new number.
|
|
313
319
|
shape="circle" reuses Avatar's own shape="circle" value (radius.full)
|
|
314
320
|
the same way, measured live on a real Attio person avatar. */
|
|
315
|
-
& .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}; }
|
|
316
322
|
& .crisp-datatable-avatar[data-shape="circle"] { border-radius: ${tokens_1.contract.radius.full}; }
|
|
317
|
-
|
|
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}; }
|
|
318
339
|
& .crisp-datatable-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
|
|
319
340
|
& .crisp-datatable-tags { display: flex; align-items: center; gap: ${tokens_1.contract.space["1"]}; overflow: hidden; }
|
|
320
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); }
|
|
@@ -325,6 +346,24 @@ const config = (0, core_1.defineRecipe)({
|
|
|
325
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}); }
|
|
326
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}); }
|
|
327
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}; }
|
|
328
367
|
& .crisp-datatable-num { font-variant-numeric: tabular-nums; }
|
|
329
368
|
& .crisp-datatable-muted { color: ${tokens_1.contract.fgMuted}; }
|
|
330
369
|
/* crisp#822 -- a date/datetime cell's danger/overdue tone: same token as
|
|
@@ -335,7 +374,7 @@ const config = (0, core_1.defineRecipe)({
|
|
|
335
374
|
own .crisp-recordstable-link, which this mirrors: no underline at
|
|
336
375
|
rest, underline on hover, own-colour text rather than a browser-blue
|
|
337
376
|
link. */
|
|
338
|
-
& .crisp-datatable-link { color: ${tokens_1.contract.fgPrimary}; text-decoration: none; overflow:
|
|
377
|
+
& .crisp-datatable-link { color: ${tokens_1.contract.fgPrimary}; text-decoration: none; overflow: clip; text-overflow: ellipsis; }
|
|
339
378
|
& .crisp-datatable-link:hover { text-decoration: underline; }
|
|
340
379
|
/* phone cell type/editor (#765) -- measured live: the dial-code prefix
|
|
341
380
|
is a muted rgba(0,0,0,0.63) at 14px, matching every other muted-text
|
|
@@ -58,7 +58,7 @@ const fromDate = (d) => ({
|
|
|
58
58
|
* popover. This is what `DatePicker` used to be; `DatePicker` is now
|
|
59
59
|
* seed-design's bare calendar, and this composes it.
|
|
60
60
|
*/
|
|
61
|
-
function DatePickerField({ value, defaultValue, onValueChange, onChange, placeholder: placeholderProp, variant = "default", format = defaultFormat, clearable = true, clearLabel: clearLabelProp, presets, calendarProps, "aria-label": ariaLabel, className, ...rest }) {
|
|
61
|
+
function DatePickerField({ value, defaultValue, onValueChange, onChange, placeholder: placeholderProp, variant = "default", width = "full", format = defaultFormat, clearable = true, clearLabel: clearLabelProp, presets, calendarProps, "aria-label": ariaLabel, className, ...rest }) {
|
|
62
62
|
// crisp/#471: same resolution order as Select's own.
|
|
63
63
|
const placeholder = (0, core_1.useCrispMessage)(placeholderProp, "Set date…");
|
|
64
64
|
const clearLabel = (0, core_1.useCrispMessage)(clearLabelProp, "Clear date");
|
|
@@ -79,7 +79,7 @@ function DatePickerField({ value, defaultValue, onValueChange, onChange, placeho
|
|
|
79
79
|
onValueChange?.(null);
|
|
80
80
|
onChange?.(null);
|
|
81
81
|
};
|
|
82
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: (0, datepickerfield_recipe_1.datepickerfieldRecipe)({ className }), ...rest, children: (0, jsx_runtime_1.jsxs)("div", { className: "crisp-datepickerfield-box", "data-ghost": variant === "ghost" ? "" : undefined, "data-placeholder": selected ? undefined : "", children: [(0, jsx_runtime_1.jsx)(popover_1.Popover, { open: open, onOpenChange: setOpen, "aria-label": ariaLabel, trigger: (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-datepickerfield-trigger", "aria-label": ariaLabel, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CalendarDays, { size: 15, strokeWidth: 1.75, "aria-hidden": "true" }), selected ? format(selected) : placeholder] }), children: (0, jsx_runtime_1.jsxs)("div", { className: "crisp-datepickerfield-panel", children: [(0, jsx_runtime_1.jsx)(datepicker_1.DatePicker
|
|
82
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, datepickerfield_recipe_1.datepickerfieldRecipe)({ width, className }), ...rest, children: (0, jsx_runtime_1.jsxs)("div", { className: "crisp-datepickerfield-box", "data-ghost": variant === "ghost" ? "" : undefined, "data-placeholder": selected ? undefined : "", children: [(0, jsx_runtime_1.jsx)(popover_1.Popover, { open: open, onOpenChange: setOpen, "aria-label": ariaLabel, trigger: (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-datepickerfield-trigger", "aria-label": ariaLabel, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CalendarDays, { size: 15, strokeWidth: 1.75, "aria-hidden": "true" }), selected ? format(selected) : placeholder] }), children: (0, jsx_runtime_1.jsxs)("div", { className: "crisp-datepickerfield-panel", children: [(0, jsx_runtime_1.jsx)(datepicker_1.DatePicker
|
|
83
83
|
// DatePickerProps is a union over selectionMode, and TypeScript
|
|
84
84
|
// cannot narrow it through a spread: it tries every branch and
|
|
85
85
|
// reports the range one as missing props. The field is always
|
|
@@ -13,7 +13,7 @@ const config = (0, core_1.defineRecipe)({
|
|
|
13
13
|
display: inline-flex; font-family: ${tokens_1.contract.font.sans};
|
|
14
14
|
|
|
15
15
|
& .crisp-datepickerfield-box {
|
|
16
|
-
display: inline-flex; align-items: center;
|
|
16
|
+
display: inline-flex; align-items: center; width: 100%;
|
|
17
17
|
box-sizing: border-box; height: 32px; margin: 0;
|
|
18
18
|
border-radius: ${tokens_1.contract.radius.md}; background: transparent;
|
|
19
19
|
box-shadow: inset 0 0 0 1px color-mix(in srgb, ${tokens_1.contract.fgPrimary} 7%, transparent);
|
|
@@ -22,6 +22,7 @@ const config = (0, core_1.defineRecipe)({
|
|
|
22
22
|
& .crisp-datepickerfield-box[data-ghost] { background: transparent; box-shadow: none; }
|
|
23
23
|
& .crisp-datepickerfield-box[data-ghost]:hover { background: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 4%, transparent); }
|
|
24
24
|
& .crisp-datepickerfield-trigger {
|
|
25
|
+
flex: 1; min-width: 0;
|
|
25
26
|
display: inline-flex; align-items: center; gap: ${tokens_1.contract.space["2"]};
|
|
26
27
|
height: 100%; padding: 0 ${tokens_1.contract.space["2.5"]}; margin: 0;
|
|
27
28
|
border: none; background: none; color: inherit; font-family: inherit;
|
|
@@ -51,8 +52,20 @@ const config = (0, core_1.defineRecipe)({
|
|
|
51
52
|
}
|
|
52
53
|
& .crisp-datepickerfield-preset:hover { background: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 8%, transparent); }
|
|
53
54
|
`,
|
|
54
|
-
variants: {
|
|
55
|
-
|
|
55
|
+
variants: {
|
|
56
|
+
// crisp#980: full (default) fills its container, matching Select's own
|
|
57
|
+
// width variant/default -- so a form composing DatePickerField alongside
|
|
58
|
+
// Input/Select via FormField gets one consistent column width across
|
|
59
|
+
// every field type, not just some of them. auto sizes to content, the
|
|
60
|
+
// behaviour every consumer got unconditionally before this.
|
|
61
|
+
width: {
|
|
62
|
+
full: `width: 100%;`,
|
|
63
|
+
auto: `width: auto;`,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
defaultVariants: {
|
|
67
|
+
width: "full",
|
|
68
|
+
},
|
|
56
69
|
compoundVariants: [],
|
|
57
70
|
});
|
|
58
71
|
exports.datepickerfieldRecipe = Object.assign((0, core_1.resolveRecipe)(config), {
|
|
@@ -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,
|
|
@@ -144,12 +177,28 @@ function Menu({ trigger, children, align = "start", open: openProp, defaultOpen,
|
|
|
144
177
|
document.addEventListener("keydown", onKey);
|
|
145
178
|
return () => document.removeEventListener("keydown", onKey);
|
|
146
179
|
}, [open, close]);
|
|
147
|
-
const { onKeyDown: onContentKeyDown } = (0, menu_keyboard_1.useMenuKeyboard)({
|
|
180
|
+
const { onKeyDown: onContentKeyDown, items } = (0, menu_keyboard_1.useMenuKeyboard)({
|
|
148
181
|
open,
|
|
149
182
|
close,
|
|
150
183
|
dismiss: () => setOpen(false),
|
|
151
184
|
contentRef,
|
|
152
185
|
});
|
|
186
|
+
// Roving tabindex (crisp#964): every item hardcodes tabIndex={-1} for the
|
|
187
|
+
// arrow-key model above, which means none of them is ever a real Tab stop
|
|
188
|
+
// on its own -- kept in sync with wherever focus actually lands, same as
|
|
189
|
+
// MenuSheet's identical fix (#966).
|
|
190
|
+
const onContentFocus = React.useCallback((e) => {
|
|
191
|
+
for (const el of items())
|
|
192
|
+
el.tabIndex = -1;
|
|
193
|
+
e.target.tabIndex = 0;
|
|
194
|
+
}, [items]);
|
|
195
|
+
React.useEffect(() => {
|
|
196
|
+
if (!open)
|
|
197
|
+
return;
|
|
198
|
+
const [first] = items();
|
|
199
|
+
if (first)
|
|
200
|
+
first.tabIndex = 0;
|
|
201
|
+
}, [open, items]);
|
|
153
202
|
const triggerEl = React.cloneElement(trigger, {
|
|
154
203
|
ref: triggerRef,
|
|
155
204
|
id: triggerId,
|
|
@@ -165,18 +214,25 @@ function Menu({ trigger, children, align = "start", open: openProp, defaultOpen,
|
|
|
165
214
|
});
|
|
166
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
|
|
167
216
|
? `crisp-menu-content ${contentClassName}`
|
|
168
|
-
: "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, 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 }) }) }))] }));
|
|
169
218
|
}
|
|
170
219
|
Menu.displayName = "Menu";
|
|
171
|
-
|
|
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) {
|
|
172
227
|
const ctx = React.useContext(MenuContext);
|
|
173
|
-
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);
|
|
174
230
|
onSelect?.();
|
|
175
231
|
if (closeOnSelect)
|
|
176
232
|
ctx?.close();
|
|
177
|
-
}, 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 })] }));
|
|
178
|
-
}
|
|
179
|
-
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";
|
|
180
236
|
function MenuCheckboxItem({ children, checked, onCheckedChange, disabled, }) {
|
|
181
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 })] }));
|
|
182
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}; }
|
|
@@ -24,7 +24,13 @@ const config = (0, core_1.defineRecipe)({
|
|
|
24
24
|
(padding: 0 12px) and independently on a body cell's text inset
|
|
25
25
|
(getBoundingClientRect delta from the cell edge). Matches
|
|
26
26
|
ColumnCalc's own already-correct 12px trigger inset. */
|
|
27
|
-
|
|
27
|
+
/* #719: overflow: clip, not hidden -- both render the ellipsis
|
|
28
|
+
identically, but hidden still honours a programmatic scrollLeft
|
|
29
|
+
assignment (a screenshot tool, a browser extension) even though it
|
|
30
|
+
already blocks user-driven wheel/scrollbar input; clip leaves no
|
|
31
|
+
scroll position for anything to move, so the truncated text can
|
|
32
|
+
never be panned out of view. */
|
|
33
|
+
& th, & td { position: relative; height: ${tokens_1.contract.size.tableRow}; padding: 0 ${tokens_1.contract.space["3"]}; border-bottom: 1px solid ${tokens_1.contract.borderSubtle}; border-inline-end: 1px solid ${tokens_1.contract.borderSubtle}; text-align: start; vertical-align: middle; white-space: nowrap; overflow: clip; text-overflow: ellipsis; }
|
|
28
34
|
/* #554: sticky on the vertical axis, mirroring RecordsTable's own
|
|
29
35
|
\`.crisp-recordstable-th\`. z-index 2 sits above a plain body cell (auto)
|
|
30
36
|
and below a sticky-column corner cell (DataTable's \`th[data-sticky]\`,
|