@crisp-ui-kit/crisp 0.56.0 → 0.57.1
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/accentpicker.css +5 -0
- package/dist/accentpicker.d.ts +7 -0
- package/dist/accentpicker.layered.css +7 -0
- package/dist/avatar.css +1 -1
- package/dist/avatar.layered.css +1 -1
- package/dist/badge.css +2 -2
- package/dist/badge.layered.css +2 -2
- package/dist/button.css +3 -3
- package/dist/button.layered.css +3 -3
- package/dist/callout.css +6 -0
- package/dist/callout.d.ts +2 -2
- package/dist/callout.layered.css +6 -0
- package/dist/cjs/components/accentpicker/accentpicker.js +66 -0
- package/dist/cjs/components/accentpicker/accentpicker.recipe.js +25 -0
- package/dist/cjs/components/accentpicker/index.js +7 -0
- package/dist/cjs/components/avatar/avatar.recipe.js +4 -1
- package/dist/cjs/components/badge/badge.recipe.js +16 -2
- package/dist/cjs/components/button/button.recipe.js +16 -6
- package/dist/cjs/components/callout/callout.js +2 -2
- package/dist/cjs/components/callout/callout.recipe.js +15 -2
- package/dist/cjs/components/input/input.js +2 -2
- package/dist/cjs/components/input/input.recipe.js +14 -0
- package/dist/cjs/components/menu/menu.js +2 -2
- package/dist/cjs/components/menu/menu.recipe.js +8 -0
- package/dist/cjs/components/multiselect/multiselect.js +23 -10
- package/dist/cjs/components/multiselect/multiselect.recipe.js +104 -65
- package/dist/cjs/components/progress/progress.js +21 -4
- package/dist/cjs/components/progress/progress.recipe.js +30 -0
- package/dist/cjs/components/select/listbox-keyboard.js +7 -1
- package/dist/cjs/components/select/select.js +24 -11
- package/dist/cjs/components/select/select.recipe.js +177 -78
- package/dist/cjs/components/tabletoolbar/tabletoolbar.js +3 -3
- package/dist/cjs/components/tabletoolbar/tabletoolbar.recipe.js +26 -1
- package/dist/cjs/components/tabs/tabs.js +63 -4
- package/dist/cjs/components/tabs/tabs.recipe.js +13 -0
- package/dist/cjs/components/text/text.recipe.js +8 -7
- package/dist/cjs/components/textarea/textarea.js +3 -2
- package/dist/cjs/components/textarea/textarea.recipe.js +2 -1
- package/dist/cjs/components/textlink/textlink.js +2 -2
- package/dist/cjs/components/textlink/textlink.recipe.js +24 -3
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/product/recordpage/recordpage.js +61 -7
- package/dist/cjs/tokens/elevation.js +7 -0
- package/dist/cjs/tokens/palette.js +120 -25
- package/dist/cjs/tokens/scale.js +9 -0
- package/dist/cjs/tokens/semantic.js +42 -0
- package/dist/esm/components/accentpicker/accentpicker.js +30 -0
- package/dist/esm/components/accentpicker/accentpicker.recipe.js +22 -0
- package/dist/esm/components/accentpicker/index.js +2 -0
- package/dist/esm/components/avatar/avatar.recipe.js +4 -1
- package/dist/esm/components/badge/badge.recipe.js +16 -2
- package/dist/esm/components/button/button.recipe.js +16 -6
- package/dist/esm/components/callout/callout.js +2 -2
- package/dist/esm/components/callout/callout.recipe.js +15 -2
- package/dist/esm/components/input/input.js +3 -3
- package/dist/esm/components/input/input.recipe.js +14 -0
- package/dist/esm/components/menu/menu.js +2 -2
- package/dist/esm/components/menu/menu.recipe.js +8 -0
- package/dist/esm/components/multiselect/multiselect.js +23 -10
- package/dist/esm/components/multiselect/multiselect.recipe.js +104 -65
- package/dist/esm/components/progress/progress.js +22 -5
- package/dist/esm/components/progress/progress.recipe.js +30 -0
- package/dist/esm/components/select/listbox-keyboard.js +7 -1
- package/dist/esm/components/select/select.js +24 -11
- package/dist/esm/components/select/select.recipe.js +177 -78
- package/dist/esm/components/tabletoolbar/tabletoolbar.js +3 -3
- package/dist/esm/components/tabletoolbar/tabletoolbar.recipe.js +26 -1
- package/dist/esm/components/tabs/tabs.js +63 -4
- package/dist/esm/components/tabs/tabs.recipe.js +13 -0
- package/dist/esm/components/text/text.recipe.js +8 -7
- package/dist/esm/components/textarea/textarea.js +3 -2
- package/dist/esm/components/textarea/textarea.recipe.js +2 -1
- package/dist/esm/components/textlink/textlink.js +2 -2
- package/dist/esm/components/textlink/textlink.recipe.js +24 -3
- package/dist/esm/index.js +1 -0
- package/dist/esm/product/recordpage/recordpage.js +62 -8
- package/dist/esm/tokens/elevation.js +7 -0
- package/dist/esm/tokens/palette.js +120 -25
- package/dist/esm/tokens/scale.js +9 -0
- package/dist/esm/tokens/semantic.js +42 -0
- package/dist/input.css +11 -0
- package/dist/input.d.ts +2 -2
- package/dist/input.layered.css +11 -0
- package/dist/menu.css +8 -0
- package/dist/menu.layered.css +8 -0
- package/dist/multiselect.css +57 -29
- package/dist/multiselect.d.ts +3 -1
- package/dist/multiselect.layered.css +57 -29
- package/dist/native/tokens.d.ts +1 -1
- package/dist/native/tokens.js +82 -28
- package/dist/progress.css +3 -0
- package/dist/progress.layered.css +3 -0
- package/dist/select.css +100 -42
- package/dist/select.d.ts +3 -2
- package/dist/select.layered.css +100 -42
- package/dist/styles.css +268 -93
- package/dist/styles.layered.css +268 -93
- package/dist/tabletoolbar.css +8 -1
- package/dist/tabletoolbar.layered.css +8 -1
- package/dist/tabs.css +6 -0
- package/dist/tabs.layered.css +6 -0
- package/dist/text.css +1 -1
- package/dist/text.layered.css +1 -1
- package/dist/textarea.css +2 -1
- package/dist/textarea.layered.css +2 -1
- package/dist/textlink.css +11 -2
- package/dist/textlink.d.ts +2 -1
- package/dist/textlink.layered.css +11 -2
- package/dist/tokens.css +43 -11
- package/dist/tokens.json +82 -28
- package/dist/types/components/accentpicker/accentpicker.d.ts +23 -0
- package/dist/types/components/accentpicker/accentpicker.recipe.d.ts +3 -0
- package/dist/types/components/accentpicker/index.d.ts +2 -0
- package/dist/types/components/button/button.recipe.d.ts +2 -2
- package/dist/types/components/callout/callout.d.ts +9 -1
- package/dist/types/components/callout/callout.recipe.d.ts +12 -2
- package/dist/types/components/input/input.d.ts +14 -0
- package/dist/types/components/input/input.recipe.d.ts +3 -0
- package/dist/types/components/menu/menu.d.ts +7 -1
- package/dist/types/components/multiselect/multiselect.d.ts +25 -6
- package/dist/types/components/multiselect/multiselect.recipe.d.ts +27 -0
- package/dist/types/components/progress/progress.d.ts +16 -4
- package/dist/types/components/progress/progress.recipe.d.ts +22 -0
- package/dist/types/components/select/listbox-keyboard.d.ts +10 -1
- package/dist/types/components/select/select.d.ts +29 -6
- package/dist/types/components/select/select.recipe.d.ts +25 -10
- package/dist/types/components/tabletoolbar/tabletoolbar.d.ts +14 -0
- package/dist/types/components/tabs/tabs.d.ts +9 -1
- package/dist/types/components/textarea/textarea.d.ts +16 -0
- package/dist/types/components/textlink/textlink.d.ts +8 -1
- package/dist/types/components/textlink/textlink.recipe.d.ts +10 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/product/recordpage/recordpage.d.ts +61 -1
- package/dist/types/tokens/contract.d.ts +16 -3
- package/dist/types/tokens/elevation.d.ts +7 -0
- package/dist/types/tokens/palette.d.ts +55 -11
- package/dist/types/tokens/scale.d.ts +6 -0
- package/dist/types/tokens/semantic.d.ts +33 -0
- package/package.json +6 -1
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
.crisp-accentpicker {
|
|
2
|
+
display: flex; gap: var(--crisp-space-2);
|
|
3
|
+
& .crisp-accentpicker-swatch { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0; margin: 0; border-radius: var(--crisp-radius-full); border: 1px solid transparent; background: none; font-family: inherit; cursor: pointer; }
|
|
4
|
+
& .crisp-accentpicker-swatch:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 2px; }
|
|
5
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
@layer crisp-components {
|
|
2
|
+
.crisp-accentpicker {
|
|
3
|
+
display: flex; gap: var(--crisp-space-2);
|
|
4
|
+
& .crisp-accentpicker-swatch { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0; margin: 0; border-radius: var(--crisp-radius-full); border: 1px solid transparent; background: none; font-family: inherit; cursor: pointer; }
|
|
5
|
+
& .crisp-accentpicker-swatch:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 2px; }
|
|
6
|
+
}
|
|
7
|
+
}
|
package/dist/avatar.css
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
background: var(--crisp-bg-raised); color: var(--crisp-fg-neutral-muted); box-shadow: inset 0 0 0 1px var(--crisp-border-default);
|
|
25
25
|
}
|
|
26
26
|
.crisp-avatar--tone_brand {
|
|
27
|
-
background: var(--crisp-bg-brand-
|
|
27
|
+
background: var(--crisp-bg-brand-contrast); color: #fff;
|
|
28
28
|
}
|
|
29
29
|
.crisp-avatar--tone_orange {
|
|
30
30
|
background: var(--crisp-bg-orange); color: #fff;
|
package/dist/avatar.layered.css
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
background: var(--crisp-bg-raised); color: var(--crisp-fg-neutral-muted); box-shadow: inset 0 0 0 1px var(--crisp-border-default);
|
|
26
26
|
}
|
|
27
27
|
.crisp-avatar--tone_brand {
|
|
28
|
-
background: var(--crisp-bg-brand-
|
|
28
|
+
background: var(--crisp-bg-brand-contrast); color: #fff;
|
|
29
29
|
}
|
|
30
30
|
.crisp-avatar--tone_orange {
|
|
31
31
|
background: var(--crisp-bg-orange); color: #fff;
|
package/dist/badge.css
CHANGED
|
@@ -36,13 +36,13 @@
|
|
|
36
36
|
|
|
37
37
|
}
|
|
38
38
|
.crisp-badge--compound_0 {
|
|
39
|
-
background: var(--crisp-bg-brand-
|
|
39
|
+
background: var(--crisp-bg-brand-contrast); color: var(--crisp-fg-on-brand); box-shadow: none;
|
|
40
40
|
}
|
|
41
41
|
.crisp-badge--compound_1 {
|
|
42
42
|
background: var(--crisp-bg-success); color: var(--crisp-fg-on-tone); box-shadow: none;
|
|
43
43
|
}
|
|
44
44
|
.crisp-badge--compound_2 {
|
|
45
|
-
background: var(--crisp-bg-warning); color: var(--crisp-fg-on-tone); box-shadow: none;
|
|
45
|
+
background: var(--crisp-bg-warning-solid); color: var(--crisp-fg-on-tone); box-shadow: none;
|
|
46
46
|
}
|
|
47
47
|
.crisp-badge--compound_3 {
|
|
48
48
|
background: var(--crisp-bg-danger); color: var(--crisp-fg-on-tone); box-shadow: none;
|
package/dist/badge.layered.css
CHANGED
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
|
|
38
38
|
}
|
|
39
39
|
.crisp-badge--compound_0 {
|
|
40
|
-
background: var(--crisp-bg-brand-
|
|
40
|
+
background: var(--crisp-bg-brand-contrast); color: var(--crisp-fg-on-brand); box-shadow: none;
|
|
41
41
|
}
|
|
42
42
|
.crisp-badge--compound_1 {
|
|
43
43
|
background: var(--crisp-bg-success); color: var(--crisp-fg-on-tone); box-shadow: none;
|
|
44
44
|
}
|
|
45
45
|
.crisp-badge--compound_2 {
|
|
46
|
-
background: var(--crisp-bg-warning); color: var(--crisp-fg-on-tone); box-shadow: none;
|
|
46
|
+
background: var(--crisp-bg-warning-solid); color: var(--crisp-fg-on-tone); box-shadow: none;
|
|
47
47
|
}
|
|
48
48
|
.crisp-badge--compound_3 {
|
|
49
49
|
background: var(--crisp-bg-danger); color: var(--crisp-fg-on-tone); box-shadow: none;
|
package/dist/button.css
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
&:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
4
4
|
}
|
|
5
5
|
.crisp-button--intent_primary {
|
|
6
|
-
background: var(--crisp-bg-brand-
|
|
7
|
-
&:hover {
|
|
8
|
-
&:active {
|
|
6
|
+
background: var(--crisp-bg-brand-contrast); color: var(--crisp-fg-on-brand); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.06), 0 2px 4px -2px rgba(38,109,240,0.12), 0 3px 6px -2px rgba(38,109,240,0.08);
|
|
7
|
+
&:hover { filter: brightness(0.96); }
|
|
8
|
+
&:active { filter: brightness(0.92); }
|
|
9
9
|
}
|
|
10
10
|
.crisp-button--intent_neutral {
|
|
11
11
|
background: var(--crisp-bg-surface); color: var(--crisp-fg-primary); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04);
|
package/dist/button.layered.css
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
&:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
5
5
|
}
|
|
6
6
|
.crisp-button--intent_primary {
|
|
7
|
-
background: var(--crisp-bg-brand-
|
|
8
|
-
&:hover {
|
|
9
|
-
&:active {
|
|
7
|
+
background: var(--crisp-bg-brand-contrast); color: var(--crisp-fg-on-brand); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.06), 0 2px 4px -2px rgba(38,109,240,0.12), 0 3px 6px -2px rgba(38,109,240,0.08);
|
|
8
|
+
&:hover { filter: brightness(0.96); }
|
|
9
|
+
&:active { filter: brightness(0.92); }
|
|
10
10
|
}
|
|
11
11
|
.crisp-button--intent_neutral {
|
|
12
12
|
background: var(--crisp-bg-surface); color: var(--crisp-fg-primary); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04);
|
package/dist/callout.css
CHANGED
|
@@ -14,3 +14,9 @@
|
|
|
14
14
|
&[data-tone="danger"] { background: color-mix(in srgb, var(--crisp-bg-danger) 10%, transparent); }
|
|
15
15
|
&[data-tone="danger"] .crisp-callout-icon { color: var(--crisp-bg-danger); }
|
|
16
16
|
}
|
|
17
|
+
.crisp-callout--bordered_true {
|
|
18
|
+
border: 1px solid var(--crisp-ring-brand-soft); border-radius: var(--crisp-radius-xl); padding: var(--crisp-space-2) var(--crisp-space-3); background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent);
|
|
19
|
+
}
|
|
20
|
+
.crisp-callout--bordered_false {
|
|
21
|
+
|
|
22
|
+
}
|
package/dist/callout.d.ts
CHANGED
package/dist/callout.layered.css
CHANGED
|
@@ -14,5 +14,11 @@
|
|
|
14
14
|
&[data-tone="warning"] .crisp-callout-icon { color: var(--crisp-bg-warning); }
|
|
15
15
|
&[data-tone="danger"] { background: color-mix(in srgb, var(--crisp-bg-danger) 10%, transparent); }
|
|
16
16
|
&[data-tone="danger"] .crisp-callout-icon { color: var(--crisp-bg-danger); }
|
|
17
|
+
}
|
|
18
|
+
.crisp-callout--bordered_true {
|
|
19
|
+
border: 1px solid var(--crisp-ring-brand-soft); border-radius: var(--crisp-radius-xl); padding: var(--crisp-space-2) var(--crisp-space-3); background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent);
|
|
20
|
+
}
|
|
21
|
+
.crisp-callout--bordered_false {
|
|
22
|
+
|
|
17
23
|
}
|
|
18
24
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.AccentPicker = AccentPicker;
|
|
37
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
38
|
+
const React = __importStar(require("react"));
|
|
39
|
+
const radiogroup_1 = require("../radiogroup");
|
|
40
|
+
const accentpicker_recipe_1 = require("./accentpicker.recipe");
|
|
41
|
+
/**
|
|
42
|
+
* A row of selectable colour swatches — Attio's own accent-colour picker
|
|
43
|
+
* (Settings > Appearance). Not a fixed palette: pass the colours (and the
|
|
44
|
+
* accent isn't crisp's concern to theme the app with — this only picks one).
|
|
45
|
+
* Same roving-focus/arrow-key model every other crisp radio-like control
|
|
46
|
+
* shares (`useRadioGroupKeyboard`, also used by `RadioGroup` and
|
|
47
|
+
* `Segmented`).
|
|
48
|
+
*/
|
|
49
|
+
function AccentPicker({ colors, value, defaultValue, onValueChange, className, onKeyDown: onKeyDownProp, ...rest }) {
|
|
50
|
+
const [internal, setInternal] = React.useState(defaultValue);
|
|
51
|
+
const selected = value ?? internal;
|
|
52
|
+
const select = (v) => {
|
|
53
|
+
if (value === undefined)
|
|
54
|
+
setInternal(v);
|
|
55
|
+
onValueChange?.(v);
|
|
56
|
+
};
|
|
57
|
+
const { onKeyDown, groupRef } = (0, radiogroup_1.useRadioGroupKeyboard)({ select });
|
|
58
|
+
return ((0, jsx_runtime_1.jsx)("div", { ref: groupRef, role: "radiogroup", className: (0, accentpicker_recipe_1.accentpickerRecipe)({ className }), ...rest, onKeyDown: (e) => {
|
|
59
|
+
onKeyDown(e);
|
|
60
|
+
onKeyDownProp?.(e);
|
|
61
|
+
}, children: colors.map((color) => {
|
|
62
|
+
const checked = selected === color;
|
|
63
|
+
return ((0, jsx_runtime_1.jsx)("button", { type: "button", role: "radio", "aria-checked": checked, "aria-label": color, "data-value": color, tabIndex: checked ? 0 : -1, className: "crisp-accentpicker-swatch", style: { borderColor: checked ? color : "transparent" }, onClick: () => select(color), children: (0, jsx_runtime_1.jsx)("svg", { width: "22", height: "22", viewBox: "0 0 22 22", fill: "none", "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("circle", { cx: "11", cy: "11", r: "9", fill: color }) }) }, color));
|
|
64
|
+
}) }));
|
|
65
|
+
}
|
|
66
|
+
AccentPicker.displayName = "AccentPicker";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.accentpickerRecipe = void 0;
|
|
4
|
+
const core_1 = require("../../core");
|
|
5
|
+
const tokens_1 = require("../../tokens");
|
|
6
|
+
// A row of selectable colour swatches — measured live on Attio's Appearance
|
|
7
|
+
// settings page (crisp#635): `role="radiogroup"`, `display: flex; gap: 8px`.
|
|
8
|
+
// Each swatch is a 24x24 circular button, `border: 1px solid transparent`
|
|
9
|
+
// at rest; the CHECKED swatch's border switches to its own colour (not a
|
|
10
|
+
// fixed brand ring) — measured directly on the DOM (`border: 1px solid
|
|
11
|
+
// rgb(38,109,240)` on the checked blue swatch, `1px solid rgba(0,0,0,0)` on
|
|
12
|
+
// every unchecked one). That per-swatch colour is data, not a class, so it's
|
|
13
|
+
// set inline by the component, not here. Inside sits a 22x22 SVG with one
|
|
14
|
+
// solid r=9 (18px) circle -- no separate ring/dot layer, contrary to an
|
|
15
|
+
// earlier, less precise read of this same control.
|
|
16
|
+
const config = (0, core_1.defineRecipe)({
|
|
17
|
+
name: "accentpicker",
|
|
18
|
+
base: `display: flex; gap: ${tokens_1.contract.space["2"]};
|
|
19
|
+
& .crisp-accentpicker-swatch { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center;
|
|
20
|
+
width: 24px; height: 24px; padding: 0; margin: 0; border-radius: ${tokens_1.contract.radius.full}; border: 1px solid transparent;
|
|
21
|
+
background: none; font-family: inherit; cursor: pointer; }
|
|
22
|
+
& .crisp-accentpicker-swatch:focus-visible { outline: 2px solid ${tokens_1.contract.bgBrandSolid}; outline-offset: 2px; }`,
|
|
23
|
+
});
|
|
24
|
+
exports.accentpickerRecipe = (0, core_1.resolveRecipe)(config);
|
|
25
|
+
exports.default = config;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.accentpickerRecipe = exports.AccentPicker = void 0;
|
|
4
|
+
var accentpicker_1 = require("./accentpicker");
|
|
5
|
+
Object.defineProperty(exports, "AccentPicker", { enumerable: true, get: function () { return accentpicker_1.AccentPicker; } });
|
|
6
|
+
var accentpicker_recipe_1 = require("./accentpicker.recipe");
|
|
7
|
+
Object.defineProperty(exports, "accentpickerRecipe", { enumerable: true, get: function () { return accentpicker_recipe_1.accentpickerRecipe; } });
|
|
@@ -39,7 +39,10 @@ const spec = (0, core_1.defineSpec)({
|
|
|
39
39
|
color: tokens_1.contract.fgNeutralMuted,
|
|
40
40
|
boxShadow: `inset 0 0 0 1px ${tokens_1.contract.borderDefault}`,
|
|
41
41
|
},
|
|
42
|
-
|
|
42
|
+
// your-moon/crisp#897: `bgBrandContrast`, the darker AA-safe sibling
|
|
43
|
+
// of the accent blue (`bgBrandSolid`, #0298d9, only 3.23:1 with
|
|
44
|
+
// white) -- keeps white text, matching every other tone here.
|
|
45
|
+
brand: { background: tokens_1.contract.bgBrandContrast, color: "#fff" },
|
|
43
46
|
orange: { background: tokens_1.contract.bgOrange, color: "#fff" },
|
|
44
47
|
cyan: { background: tokens_1.contract.bgCyan, color: "#fff" },
|
|
45
48
|
purple: { background: tokens_1.contract.bgPurple, color: "#fff" },
|
|
@@ -129,8 +129,14 @@ const spec = (0, core_1.defineSpec)({
|
|
|
129
129
|
{
|
|
130
130
|
variant: "solid",
|
|
131
131
|
tone: "brand",
|
|
132
|
+
// your-moon/crisp#897: `bgBrandContrast`, not `bgBrandSolid` — white
|
|
133
|
+
// text on the exact accent blue (#0298d9) only clears 3.23:1;
|
|
134
|
+
// `bgBrandContrast` is the darker sibling built to clear 4.5:1+ with
|
|
135
|
+
// white, so `fgOnBrand` (white) stays right rather than `fgOnTone`
|
|
136
|
+
// (ink read off-brand next to solid `success`/`warning`/`danger`,
|
|
137
|
+
// which really do need it).
|
|
132
138
|
decls: {
|
|
133
|
-
background: tokens_1.contract.
|
|
139
|
+
background: tokens_1.contract.bgBrandContrast,
|
|
134
140
|
color: tokens_1.contract.fgOnBrand,
|
|
135
141
|
boxShadow: "none",
|
|
136
142
|
},
|
|
@@ -143,7 +149,15 @@ const spec = (0, core_1.defineSpec)({
|
|
|
143
149
|
{
|
|
144
150
|
variant: "solid",
|
|
145
151
|
tone: "warning",
|
|
146
|
-
|
|
152
|
+
// seed-identity migration (your-moon/crisp#890): `bgWarningSolid`, not
|
|
153
|
+
// `bgWarning` — seed's own solid warning fill is a distinct, paler
|
|
154
|
+
// yellow from the accent every other tone's solid fill reuses
|
|
155
|
+
// directly (see tokens/palette.ts's `amberSolid` comment).
|
|
156
|
+
decls: {
|
|
157
|
+
background: tokens_1.contract.bgWarningSolid,
|
|
158
|
+
color: tokens_1.contract.fgOnTone,
|
|
159
|
+
boxShadow: "none",
|
|
160
|
+
},
|
|
147
161
|
},
|
|
148
162
|
{
|
|
149
163
|
variant: "solid",
|
|
@@ -30,7 +30,13 @@ const spec = (0, core_1.defineSpec)({
|
|
|
30
30
|
intent: {
|
|
31
31
|
primary: {
|
|
32
32
|
decls: {
|
|
33
|
-
|
|
33
|
+
// your-moon/crisp#897: `bgBrandContrast`, not `bgBrandSolid` —
|
|
34
|
+
// white text on the exact accent blue (#0298d9) only clears
|
|
35
|
+
// 3.23:1; `bgBrandContrast` is the darker sibling built to clear
|
|
36
|
+
// white at 4.5:1+, keeping `fgOnBrand` (white) rather than
|
|
37
|
+
// reaching for `fgOnTone` (ink read off-brand — seed's own solid
|
|
38
|
+
// buttons use white).
|
|
39
|
+
background: tokens_1.contract.bgBrandContrast,
|
|
34
40
|
color: tokens_1.contract.fgOnBrand,
|
|
35
41
|
// crisp#494: the inset ring is a black tint, not white -- live-
|
|
36
42
|
// measured on Attio's own "New Company" button as
|
|
@@ -39,12 +45,16 @@ const spec = (0, core_1.defineSpec)({
|
|
|
39
45
|
// exactly.
|
|
40
46
|
boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.06), 0 2px 4px -2px rgba(38,109,240,0.12), 0 3px 6px -2px rgba(38,109,240,0.08)",
|
|
41
47
|
},
|
|
48
|
+
// your-moon/crisp#897: a brightness filter, not a second background
|
|
49
|
+
// swap — matches `danger`'s own pattern below. `bgBrandSolidPressed`
|
|
50
|
+
// remains the accent's own hover-darken for the many OTHER
|
|
51
|
+
// consumers that pair `bgBrandSolid` with white already (out of
|
|
52
|
+
// scope for this fix; tracked separately), so reusing it here would
|
|
53
|
+
// have made primary's rest-to-hover jump inconsistent with its own
|
|
54
|
+
// rest fill's new, darker starting point.
|
|
42
55
|
parts: [
|
|
43
|
-
{ selector: "&:hover", decls: {
|
|
44
|
-
{
|
|
45
|
-
selector: "&:active",
|
|
46
|
-
decls: { background: tokens_1.contract.bgBrandSolidPressed },
|
|
47
|
-
},
|
|
56
|
+
{ selector: "&:hover", decls: { filter: "brightness(0.96)" } },
|
|
57
|
+
{ selector: "&:active", decls: { filter: "brightness(0.92)" } },
|
|
48
58
|
],
|
|
49
59
|
},
|
|
50
60
|
neutral: {
|
|
@@ -15,11 +15,11 @@ const DEFAULT_ICONS = {
|
|
|
15
15
|
* An inline callout / banner — measured from info notices. `tone` tints
|
|
16
16
|
* the background and icon; pass a `title` and/or body `children`.
|
|
17
17
|
*/
|
|
18
|
-
function Callout({ tone = "neutral", icon, title, children, action, className, ...rest }) {
|
|
18
|
+
function Callout({ tone = "neutral", icon, title, children, action, bordered, className, ...rest }) {
|
|
19
19
|
const Fallback = DEFAULT_ICONS[tone];
|
|
20
20
|
const iconNode = icon === undefined
|
|
21
21
|
? Fallback && (0, jsx_runtime_1.jsx)(Fallback, { size: 16, strokeWidth: 1.75, "aria-hidden": "true" })
|
|
22
22
|
: icon;
|
|
23
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, callout_recipe_1.calloutRecipe)({ className }), ...rest, "data-tone": tone, role: "note", children: [iconNode && (0, jsx_runtime_1.jsx)("span", { className: "crisp-callout-icon", children: iconNode }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-callout-body", children: [title != null && (0, jsx_runtime_1.jsx)("div", { className: "crisp-callout-title", children: title }), children != null && ((0, jsx_runtime_1.jsx)("div", { className: "crisp-callout-desc", children: children }))] }), action && (0, jsx_runtime_1.jsx)("div", { className: "crisp-callout-action", children: action })] }));
|
|
23
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, callout_recipe_1.calloutRecipe)({ bordered, className }), ...rest, "data-tone": tone, role: "note", children: [iconNode && (0, jsx_runtime_1.jsx)("span", { className: "crisp-callout-icon", children: iconNode }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-callout-body", children: [title != null && (0, jsx_runtime_1.jsx)("div", { className: "crisp-callout-title", children: title }), children != null && ((0, jsx_runtime_1.jsx)("div", { className: "crisp-callout-desc", children: children }))] }), action && (0, jsx_runtime_1.jsx)("div", { className: "crisp-callout-action", children: action })] }));
|
|
24
24
|
}
|
|
25
25
|
Callout.displayName = "Callout";
|
|
@@ -21,8 +21,21 @@ const config = (0, core_1.defineRecipe)({
|
|
|
21
21
|
&[data-tone="warning"] .crisp-callout-icon { color: ${tokens_1.contract.bgWarning}; }
|
|
22
22
|
&[data-tone="danger"] { background: color-mix(in srgb, ${tokens_1.contract.bgDanger} 10%, transparent); }
|
|
23
23
|
&[data-tone="danger"] .crisp-callout-icon { color: ${tokens_1.contract.bgDanger}; }`,
|
|
24
|
-
variants: {
|
|
25
|
-
|
|
24
|
+
variants: {
|
|
25
|
+
// crisp#869: a page-level banner look, measured live on Attio's Objects
|
|
26
|
+
// settings page (the "Create custom objects... Upgrade" Pro-plan
|
|
27
|
+
// nudge) — a real 1px opaque border, 12px radius, 8px/12px padding, and
|
|
28
|
+
// a 14%-brand-tinted background (the same `color-mix` ratio Badge's own
|
|
29
|
+
// soft-brand variant already uses). Only this one brand/info-toned
|
|
30
|
+
// instance was found live; `bordered` doesn't attempt a per-tone border
|
|
31
|
+
// colour for success/warning/danger — no such Attio banner was found to
|
|
32
|
+
// measure one against.
|
|
33
|
+
bordered: {
|
|
34
|
+
true: `border: 1px solid ${tokens_1.contract.ringBrandSoft}; border-radius: ${tokens_1.contract.radius.xl}; padding: ${tokens_1.contract.space["2"]} ${tokens_1.contract.space["3"]}; background: color-mix(in srgb, ${tokens_1.contract.bgBrandSolid} 14%, transparent);`,
|
|
35
|
+
false: "",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
defaultVariants: { bordered: false },
|
|
26
39
|
compoundVariants: [],
|
|
27
40
|
});
|
|
28
41
|
exports.calloutRecipe = (0, core_1.resolveRecipe)(config);
|
|
@@ -37,11 +37,11 @@ exports.Input = void 0;
|
|
|
37
37
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
38
38
|
const React = __importStar(require("react"));
|
|
39
39
|
const input_recipe_1 = require("./input.recipe");
|
|
40
|
-
exports.Input = React.forwardRef(({ size, invalid, className, style, ...props }, ref) => {
|
|
40
|
+
exports.Input = React.forwardRef(({ size, invalid, className, style, suffix, ...props }, ref) => {
|
|
41
41
|
// The wrapper exists only to host the ::after focus ring — an <input> is a
|
|
42
42
|
// replaced element and cannot have one. Everything the consumer passes
|
|
43
43
|
// still lands on the <input> itself, so `id`, `name`, `onChange`, form
|
|
44
44
|
// association and every native attribute behave exactly as before.
|
|
45
|
-
return ((0, jsx_runtime_1.
|
|
45
|
+
return ((0, jsx_runtime_1.jsxs)("span", { className: (0, input_recipe_1.inputRecipe)({ size, invalid, className }), style: style, "data-readonly": props.readOnly ? "" : undefined, children: [(0, jsx_runtime_1.jsx)("input", { ref: ref, className: "crisp-input-value", "aria-invalid": invalid === true || undefined, ...props }), suffix != null && (0, jsx_runtime_1.jsx)("span", { className: "crisp-input-suffix", children: suffix })] }));
|
|
46
46
|
});
|
|
47
47
|
exports.Input.displayName = "Input";
|
|
@@ -41,9 +41,23 @@ const config = (0, core_1.defineRecipe)({
|
|
|
41
41
|
& .crisp-input-value::placeholder { color: ${tokens_1.contract.fgMuted}; }
|
|
42
42
|
& .crisp-input-value:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
43
43
|
&:has(.crisp-input-value:disabled) { opacity: 1; }
|
|
44
|
+
|
|
45
|
+
/* crisp#634: measured live on Attio's own Settings > Profile read-only
|
|
46
|
+
primary-email field -- a tinted field, not just muted text, driven off
|
|
47
|
+
the native \`readOnly\` attribute. \`ringField\` (rgba(0,0,0,.06)) is an
|
|
48
|
+
exact match for the measured ring; the 2%-fgPrimary tint reuses the
|
|
49
|
+
same color-mix idiom every other soft crisp surface already uses. */
|
|
50
|
+
&[data-readonly] { background: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 2%, transparent); box-shadow: inset 0 0 0 1px ${tokens_1.contract.ringField}; }
|
|
51
|
+
& .crisp-input-suffix { flex-shrink: 0; margin-inline-start: ${tokens_1.contract.space["1"]}; }
|
|
44
52
|
`,
|
|
45
53
|
variants: {
|
|
46
54
|
size: {
|
|
55
|
+
// crisp#878: not a fresh click-measurement -- reuses `TableToolbar`'s
|
|
56
|
+
// own compact search box shape (`tabletoolbar.chrome.ts`'s `-search`
|
|
57
|
+
// rule), already corroborated against Attio, at the same height as
|
|
58
|
+
// `c.size.row` ("nav item · search · control height"). Same radius and
|
|
59
|
+
// padding `medium` already uses, just 4px shorter.
|
|
60
|
+
sm: `height: ${tokens_1.contract.size.row}; border-radius: ${tokens_1.contract.radius.md}; & .crisp-input-value { padding-inline: ${tokens_1.contract.space["2.5"]}; }`,
|
|
47
61
|
medium: `height: 32px; border-radius: ${tokens_1.contract.radius.md}; & .crisp-input-value { padding-inline: ${tokens_1.contract.space["2.5"]}; }`,
|
|
48
62
|
large: `height: 36px; border-radius: 10px; & .crisp-input-value { padding-inline: ${tokens_1.contract.space["3"]}; }`,
|
|
49
63
|
},
|
|
@@ -168,13 +168,13 @@ function Menu({ trigger, children, align = "start", open: openProp, defaultOpen,
|
|
|
168
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 }) }) }))] }));
|
|
169
169
|
}
|
|
170
170
|
Menu.displayName = "Menu";
|
|
171
|
-
function MenuItem({ children, icon, shortcut, danger, disabled, onSelect, closeOnSelect = true, }) {
|
|
171
|
+
function MenuItem({ children, icon, shortcut, count, danger, disabled, onSelect, closeOnSelect = true, }) {
|
|
172
172
|
const ctx = React.useContext(MenuContext);
|
|
173
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: () => {
|
|
174
174
|
onSelect?.();
|
|
175
175
|
if (closeOnSelect)
|
|
176
176
|
ctx?.close();
|
|
177
|
-
}, children: [icon, (0, jsx_runtime_1.jsx)("span", { className: "crisp-menu-item-label", children: children }), shortcut && (0, jsx_runtime_1.jsx)("span", { className: "crisp-menu-item-shortcut", children: shortcut })] }));
|
|
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
178
|
}
|
|
179
179
|
MenuItem.displayName = "MenuItem";
|
|
180
180
|
function MenuCheckboxItem({ children, checked, onCheckedChange, disabled, }) {
|
|
@@ -57,6 +57,14 @@ const config = (0, core_1.defineRecipe)({
|
|
|
57
57
|
.crisp-menu-item--danger svg { color: ${tokens_1.contract.bgDanger}; }
|
|
58
58
|
.crisp-menu-item--danger:hover, .crisp-menu-item--danger:focus-visible, .crisp-menu-item--danger[data-highlighted] { background: color-mix(in srgb, ${tokens_1.contract.bgDanger} 10%, transparent); }
|
|
59
59
|
.crisp-menu-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
60
|
+
/* crisp#875: same measured neutral chip TableToolbar's own ToolbarTool
|
|
61
|
+
count prop uses (re-confirmed on two live Attio surfaces this round:
|
|
62
|
+
the Sort tool's own "+N" overflow, a Kanban board's stage-column
|
|
63
|
+
count) -- a small badge, not bare text. */
|
|
64
|
+
.crisp-menu-item-count { flex-shrink: 0; margin-inline-start: ${tokens_1.contract.space["1.5"]}; display: inline-flex; align-items: center; height: 16px; box-sizing: border-box;
|
|
65
|
+
padding: 0 ${tokens_1.contract.space["1"]}; border-radius: ${tokens_1.contract.radius.sm}; background: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 4%, transparent);
|
|
66
|
+
box-shadow: inset 0 0 0 1px ${tokens_1.contract.borderSubtle}; font-size: ${tokens_1.contract.text.sm}; font-weight: ${tokens_1.contract.weight.medium}; color: ${tokens_1.contract.fgNeutralSoft};
|
|
67
|
+
font-variant-numeric: tabular-nums; }
|
|
60
68
|
.crisp-menu-item-shortcut { flex-shrink: 0; margin-inline-start: ${tokens_1.contract.space["3"]}; font-size: ${tokens_1.contract.text.sm}; color: ${tokens_1.contract.fgMuted}; letter-spacing: 0.02em; }
|
|
61
69
|
.crisp-menu-item-check { flex-shrink: 0; color: ${tokens_1.contract.bgBrandSolid}; }
|
|
62
70
|
.crisp-menu-item-check--placeholder { width: 15px; }
|
|
@@ -60,16 +60,18 @@ function Chip({ opt }) {
|
|
|
60
60
|
return ((0, jsx_runtime_1.jsx)("span", { className: "crisp-recordstable-tag", "data-tone": opt.tone ?? toneFor(opt.value), children: opt.label }));
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
|
-
* A multi-select / tag editor
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
63
|
+
* A multi-select / tag editor, its trigger/listbox/item chrome built to the
|
|
64
|
+
* same seed-design parity as `Select` (crisp/#882, following #867/#879) —
|
|
65
|
+
* its own chip/checkbox picker behaviour is unchanged. The outlined trigger
|
|
66
|
+
* shows the selected values as coloured chips; it opens a popover with a
|
|
67
|
+
* search field over rows of "[chip] … [checkbox]" that toggle on click (the
|
|
68
|
+
* menu stays open). Keyboard: ↑/↓ move, Enter/Space toggle, Esc closes.
|
|
67
69
|
*/
|
|
68
70
|
function MultiSelect({ options, value: valueProp, defaultValue, onValueChange, name, required,
|
|
69
71
|
// The id belongs on the trigger, not the wrapper: `<label for>` only names a
|
|
70
72
|
// LABELABLE element, so an id left on the root div meant a FormField label
|
|
71
73
|
// above this control named nothing (#247). Select already did this.
|
|
72
|
-
id, placeholder: placeholderProp, searchable = true, searchPlaceholder: searchPlaceholderProp, emptyLabel: emptyLabelProp, disabled, invalid, className, "aria-label": ariaLabel, ...rest }) {
|
|
74
|
+
id, placeholder: placeholderProp, searchable = true, searchPlaceholder: searchPlaceholderProp, emptyLabel: emptyLabelProp, disabled, readOnly, invalid, size = "small", variant = "default", className, "aria-label": ariaLabel, ...rest }) {
|
|
73
75
|
// crisp/#471: same resolution order as Select's own.
|
|
74
76
|
const placeholder = (0, core_1.useCrispMessage)(placeholderProp, "Select…");
|
|
75
77
|
const searchPlaceholder = (0, core_1.useCrispMessage)(searchPlaceholderProp, "Search…");
|
|
@@ -106,8 +108,12 @@ id, placeholder: placeholderProp, searchable = true, searchPlaceholder: searchPl
|
|
|
106
108
|
const filtered = searchable && q
|
|
107
109
|
? options.filter((o) => o.label.toLowerCase().includes(q))
|
|
108
110
|
: options;
|
|
111
|
+
// seed-design's `interactive` (crisp/#882, matching Select): disabled AND
|
|
112
|
+
// readOnly both refuse to open, but only `disabled` greys the text and
|
|
113
|
+
// removes the button from the tab order.
|
|
114
|
+
const interactive = !disabled && !readOnly;
|
|
109
115
|
const openMenu = () => {
|
|
110
|
-
if (
|
|
116
|
+
if (!interactive)
|
|
111
117
|
return;
|
|
112
118
|
const rect = triggerRef.current?.getBoundingClientRect();
|
|
113
119
|
if (rect) {
|
|
@@ -116,7 +122,7 @@ id, placeholder: placeholderProp, searchable = true, searchPlaceholder: searchPl
|
|
|
116
122
|
// direction that is (#210)
|
|
117
123
|
const { style, up: flipUp } = (0, core_1.placeFloating)({
|
|
118
124
|
rect,
|
|
119
|
-
gap: 4
|
|
125
|
+
gap: 8, // seed-design's gutter (crisp/#882, matching Select; was 4)
|
|
120
126
|
flipBelow: 300,
|
|
121
127
|
anchor: triggerRef.current,
|
|
122
128
|
});
|
|
@@ -161,6 +167,10 @@ id, placeholder: placeholderProp, searchable = true, searchPlaceholder: searchPl
|
|
|
161
167
|
close,
|
|
162
168
|
// Tab is already moving focus out; `close` would drag it back to the trigger
|
|
163
169
|
dismiss: () => setOpen(false),
|
|
170
|
+
// Space also toggles the highlighted option (crisp/#882, matching
|
|
171
|
+
// Select's Enter/Space parity) when the trigger itself owns navigation.
|
|
172
|
+
// Never when searchable -- see Select's own comment on this option.
|
|
173
|
+
commitOnSpace: !searchable,
|
|
164
174
|
});
|
|
165
175
|
// Registers the (now-portaled) listbox on the shared floating-layer stack
|
|
166
176
|
// (#339) so this doesn't get closed out from under itself when nested
|
|
@@ -198,11 +208,14 @@ id, placeholder: placeholderProp, searchable = true, searchPlaceholder: searchPl
|
|
|
198
208
|
document.addEventListener("keydown", onKey);
|
|
199
209
|
return () => document.removeEventListener("keydown", onKey);
|
|
200
210
|
}, [open, close]);
|
|
201
|
-
return ((0, jsx_runtime_1.jsxs)("div", { ref: rootRef, className: (0, multiselect_recipe_1.multiselectRecipe)({ invalid, className }), ...rest, children: [name &&
|
|
202
|
-
(value.length > 0 ? value : required ? [""] : []).map((v) => ((0, jsx_runtime_1.jsx)("input", { className: "crisp-formvalue", style: core_1.formValueStyle, name: name, value: v, required: required, tabIndex: -1, "aria-hidden": "true", onChange: () => { } }, v))), (0, jsx_runtime_1.jsxs)("button", { ref: triggerRef, id: id, type: "button", 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, disabled: disabled, "data-open": open ? "" : undefined, className: "crisp-multiselect-trigger", onClick: () => (open ? setOpen(false) : openMenu()), onKeyDown: (e) => {
|
|
211
|
+
return ((0, jsx_runtime_1.jsxs)("div", { ref: rootRef, className: (0, multiselect_recipe_1.multiselectRecipe)({ size, variant, invalid, className }), ...rest, children: [name &&
|
|
212
|
+
(value.length > 0 ? value : required ? [""] : []).map((v) => ((0, jsx_runtime_1.jsx)("input", { className: "crisp-formvalue", style: core_1.formValueStyle, name: name, value: v, required: required, tabIndex: -1, "aria-hidden": "true", onChange: () => { } }, v))), (0, jsx_runtime_1.jsxs)("button", { ref: triggerRef, id: id, type: "button", 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-multiselect-trigger", onClick: () => (open ? setOpen(false) : openMenu()), onKeyDown: (e) => {
|
|
213
|
+
if (!interactive)
|
|
214
|
+
return;
|
|
203
215
|
if (open && !searchable)
|
|
204
216
|
onNavKeys(e);
|
|
205
|
-
else if (!open &&
|
|
217
|
+
else if (!open &&
|
|
218
|
+
(e.key === "ArrowDown" || e.key === "Enter" || e.key === " ")) {
|
|
206
219
|
e.preventDefault();
|
|
207
220
|
openMenu();
|
|
208
221
|
}
|