@crisp-ui-kit/crisp 0.43.0 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chip.css +27 -0
- package/dist/chip.d.ts +7 -0
- package/dist/chip.layered.css +29 -0
- package/dist/cjs/components/chip/chip.js +58 -0
- package/dist/cjs/components/chip/chip.recipe.js +80 -0
- package/dist/cjs/components/chip/index.js +7 -0
- package/dist/cjs/components/contextmenu/contextmenu.recipe.js +6 -1
- package/dist/cjs/components/menu/menu.recipe.js +6 -1
- package/dist/cjs/components/multiselect/multiselect.recipe.js +6 -1
- package/dist/cjs/components/popover/popover.recipe.js +6 -1
- package/dist/cjs/components/select/select.recipe.js +6 -1
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/product/recordpanel/recordpanel.js +15 -2
- package/dist/contextmenu.css +6 -1
- package/dist/contextmenu.layered.css +6 -1
- package/dist/esm/components/chip/chip.js +22 -0
- package/dist/esm/components/chip/chip.recipe.js +77 -0
- package/dist/esm/components/chip/index.js +2 -0
- package/dist/esm/components/contextmenu/contextmenu.recipe.js +6 -1
- package/dist/esm/components/menu/menu.recipe.js +6 -1
- package/dist/esm/components/multiselect/multiselect.recipe.js +6 -1
- package/dist/esm/components/popover/popover.recipe.js +6 -1
- package/dist/esm/components/select/select.recipe.js +6 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/product/recordpanel/recordpanel.js +15 -2
- package/dist/menu.css +6 -1
- package/dist/menu.layered.css +6 -1
- package/dist/multiselect.css +6 -1
- package/dist/multiselect.layered.css +6 -1
- package/dist/popover.css +6 -1
- package/dist/popover.layered.css +6 -1
- package/dist/select.css +6 -1
- package/dist/select.layered.css +6 -1
- package/dist/styles.css +58 -5
- package/dist/styles.layered.css +58 -5
- package/dist/types/components/chip/chip.d.ts +47 -0
- package/dist/types/components/chip/chip.recipe.d.ts +100 -0
- package/dist/types/components/chip/index.d.ts +2 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +6 -1
package/dist/chip.css
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
.crisp-chip {
|
|
2
|
+
display: inline-flex; align-items: center; height: var(--crisp-size-chip); 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
|
+
}
|
|
4
|
+
.crisp-chip--tone_neutral {
|
|
5
|
+
background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle);
|
|
6
|
+
}
|
|
7
|
+
.crisp-chip--tone_brand {
|
|
8
|
+
background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-brand-solid) 30%, transparent);
|
|
9
|
+
}
|
|
10
|
+
.crisp-chip--tone_success {
|
|
11
|
+
background: color-mix(in srgb, var(--crisp-bg-success) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-success) 78%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-success) 30%, transparent);
|
|
12
|
+
}
|
|
13
|
+
.crisp-chip--tone_warning {
|
|
14
|
+
background: color-mix(in srgb, var(--crisp-bg-warning) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-warning) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-warning) 30%, transparent);
|
|
15
|
+
}
|
|
16
|
+
.crisp-chip--tone_danger {
|
|
17
|
+
background: color-mix(in srgb, var(--crisp-bg-danger) 15%, transparent); color: color-mix(in srgb, var(--crisp-bg-danger) 80%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-danger) 30%, transparent);
|
|
18
|
+
}
|
|
19
|
+
.crisp-chip--tone_purple {
|
|
20
|
+
background: color-mix(in srgb, var(--crisp-bg-purple) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-purple) 80%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-purple) 30%, transparent);
|
|
21
|
+
}
|
|
22
|
+
.crisp-chip--tone_cyan {
|
|
23
|
+
background: color-mix(in srgb, var(--crisp-bg-cyan) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-cyan) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-cyan) 30%, transparent);
|
|
24
|
+
}
|
|
25
|
+
.crisp-chip--tone_orange {
|
|
26
|
+
background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-orange) 30%, transparent);
|
|
27
|
+
}
|
package/dist/chip.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RecipeFn } from "../core/types";
|
|
2
|
+
|
|
3
|
+
export interface ChipVariants {
|
|
4
|
+
tone?: "neutral" | "brand" | "success" | "warning" | "danger" | "purple" | "cyan" | "orange";
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export declare const chipRecipe: RecipeFn<{ tone: { neutral: string; brand: string; success: string; warning: string; danger: string; purple: string; cyan: string; orange: string } }>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
@layer crisp-components {
|
|
2
|
+
.crisp-chip {
|
|
3
|
+
display: inline-flex; align-items: center; height: var(--crisp-size-chip); 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
|
+
}
|
|
5
|
+
.crisp-chip--tone_neutral {
|
|
6
|
+
background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle);
|
|
7
|
+
}
|
|
8
|
+
.crisp-chip--tone_brand {
|
|
9
|
+
background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-brand-solid) 30%, transparent);
|
|
10
|
+
}
|
|
11
|
+
.crisp-chip--tone_success {
|
|
12
|
+
background: color-mix(in srgb, var(--crisp-bg-success) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-success) 78%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-success) 30%, transparent);
|
|
13
|
+
}
|
|
14
|
+
.crisp-chip--tone_warning {
|
|
15
|
+
background: color-mix(in srgb, var(--crisp-bg-warning) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-warning) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-warning) 30%, transparent);
|
|
16
|
+
}
|
|
17
|
+
.crisp-chip--tone_danger {
|
|
18
|
+
background: color-mix(in srgb, var(--crisp-bg-danger) 15%, transparent); color: color-mix(in srgb, var(--crisp-bg-danger) 80%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-danger) 30%, transparent);
|
|
19
|
+
}
|
|
20
|
+
.crisp-chip--tone_purple {
|
|
21
|
+
background: color-mix(in srgb, var(--crisp-bg-purple) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-purple) 80%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-purple) 30%, transparent);
|
|
22
|
+
}
|
|
23
|
+
.crisp-chip--tone_cyan {
|
|
24
|
+
background: color-mix(in srgb, var(--crisp-bg-cyan) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-cyan) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-cyan) 30%, transparent);
|
|
25
|
+
}
|
|
26
|
+
.crisp-chip--tone_orange {
|
|
27
|
+
background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-orange) 30%, transparent);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
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.Chip = void 0;
|
|
37
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
38
|
+
const React = __importStar(require("react"));
|
|
39
|
+
const core_1 = require("../../core");
|
|
40
|
+
const chip_recipe_1 = require("./chip.recipe");
|
|
41
|
+
/**
|
|
42
|
+
* A small pill — the same measured chip RecordsTable, RecordPanel and
|
|
43
|
+
* MultiSelect already draw as `.crisp-recordstable-tag`, exported standalone
|
|
44
|
+
* for surfaces that need one without a table or a fixed option set (e.g. a
|
|
45
|
+
* free-text tag list).
|
|
46
|
+
*
|
|
47
|
+
* This ships the measured body only. Attio's removable × on a chip needs a
|
|
48
|
+
* live, populated multi-value editor to measure against, and none was
|
|
49
|
+
* reachable this round (a person's "Email addresses" field was empty on the
|
|
50
|
+
* only record checked, and "Categories" removes via a checkbox toggle, not
|
|
51
|
+
* an inline ×) — so `Chip` has no `onRemove`/remove button yet. Add one once
|
|
52
|
+
* that surface can be measured; don't guess the icon, its hit target, or its
|
|
53
|
+
* spacing from the label.
|
|
54
|
+
*/
|
|
55
|
+
exports.Chip = React.forwardRef(({ tone, className, asChild, children, ...props }, ref) => {
|
|
56
|
+
return ((0, jsx_runtime_1.jsx)(core_1.Primitive.span, { ref: ref, asChild: asChild, className: (0, chip_recipe_1.chipRecipe)({ tone, className }), ...props, children: children }));
|
|
57
|
+
});
|
|
58
|
+
exports.Chip.displayName = "Chip";
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.spec = exports.chipRecipe = void 0;
|
|
4
|
+
const core_1 = require("../../core");
|
|
5
|
+
const tokens_1 = require("../../tokens");
|
|
6
|
+
// The same measured pill RecordsTable/RecordPanel/MultiSelect already draw
|
|
7
|
+
// as ".crisp-recordstable-tag" (product/recordstable/recordstable.tag.ts's
|
|
8
|
+
// recordTagCss): 22px tall, `padding: 0 4px`, `border-radius: chip`,
|
|
9
|
+
// 14px/20px at weight 500, and a 1px inset ring in the tone's colour. That
|
|
10
|
+
// export is raw CSS written to be spliced under another component's own
|
|
11
|
+
// `&` root (RecordsTable/RecordPanel nest it inside their own recipe), so it
|
|
12
|
+
// can't be reused verbatim here — Chip's root IS the styled element, not a
|
|
13
|
+
// wrapper around one. The values below are transcribed from recordTagCss,
|
|
14
|
+
// not re-measured; keep the two in sync by hand if either changes.
|
|
15
|
+
const ring = (v, pct) => `inset 0 0 0 1px color-mix(in srgb, ${v} ${pct}%, transparent)`;
|
|
16
|
+
const soft = (v, pct) => `color-mix(in srgb, ${v} ${pct}%, transparent)`;
|
|
17
|
+
const onFg = (v, pct) => `color-mix(in srgb, ${v} ${pct}%, ${tokens_1.contract.fgPrimary})`;
|
|
18
|
+
const spec = (0, core_1.defineSpec)({
|
|
19
|
+
name: "chip",
|
|
20
|
+
base: {
|
|
21
|
+
display: "inline-flex",
|
|
22
|
+
alignItems: "center",
|
|
23
|
+
height: tokens_1.contract.size.chip,
|
|
24
|
+
paddingInline: tokens_1.contract.space["1"],
|
|
25
|
+
borderRadius: tokens_1.contract.radius.chip,
|
|
26
|
+
fontSize: tokens_1.contract.text.lg,
|
|
27
|
+
lineHeight: "20px",
|
|
28
|
+
fontWeight: tokens_1.contract.weight.medium,
|
|
29
|
+
whiteSpace: "nowrap",
|
|
30
|
+
},
|
|
31
|
+
variants: {
|
|
32
|
+
tone: {
|
|
33
|
+
neutral: {
|
|
34
|
+
background: soft(tokens_1.contract.fgPrimary, 6),
|
|
35
|
+
color: soft(tokens_1.contract.fgPrimary, 82),
|
|
36
|
+
boxShadow: `inset 0 0 0 1px ${tokens_1.contract.borderSubtle}`,
|
|
37
|
+
},
|
|
38
|
+
brand: {
|
|
39
|
+
background: soft(tokens_1.contract.bgBrandSolid, 14),
|
|
40
|
+
color: onFg(tokens_1.contract.bgBrandSolid, 82),
|
|
41
|
+
boxShadow: ring(tokens_1.contract.bgBrandSolid, 30),
|
|
42
|
+
},
|
|
43
|
+
success: {
|
|
44
|
+
background: soft(tokens_1.contract.bgSuccess, 16),
|
|
45
|
+
color: onFg(tokens_1.contract.bgSuccess, 78),
|
|
46
|
+
boxShadow: ring(tokens_1.contract.bgSuccess, 30),
|
|
47
|
+
},
|
|
48
|
+
warning: {
|
|
49
|
+
background: soft(tokens_1.contract.bgWarning, 18),
|
|
50
|
+
color: onFg(tokens_1.contract.bgWarning, 82),
|
|
51
|
+
boxShadow: ring(tokens_1.contract.bgWarning, 30),
|
|
52
|
+
},
|
|
53
|
+
danger: {
|
|
54
|
+
background: soft(tokens_1.contract.bgDanger, 15),
|
|
55
|
+
color: onFg(tokens_1.contract.bgDanger, 80),
|
|
56
|
+
boxShadow: ring(tokens_1.contract.bgDanger, 30),
|
|
57
|
+
},
|
|
58
|
+
purple: {
|
|
59
|
+
background: soft(tokens_1.contract.bgPurple, 16),
|
|
60
|
+
color: onFg(tokens_1.contract.bgPurple, 80),
|
|
61
|
+
boxShadow: ring(tokens_1.contract.bgPurple, 30),
|
|
62
|
+
},
|
|
63
|
+
cyan: {
|
|
64
|
+
background: soft(tokens_1.contract.bgCyan, 18),
|
|
65
|
+
color: onFg(tokens_1.contract.bgCyan, 82),
|
|
66
|
+
boxShadow: ring(tokens_1.contract.bgCyan, 30),
|
|
67
|
+
},
|
|
68
|
+
orange: {
|
|
69
|
+
background: soft(tokens_1.contract.bgOrange, 16),
|
|
70
|
+
color: onFg(tokens_1.contract.bgOrange, 82),
|
|
71
|
+
boxShadow: ring(tokens_1.contract.bgOrange, 30),
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
defaultVariants: { tone: "neutral" },
|
|
76
|
+
});
|
|
77
|
+
exports.spec = spec;
|
|
78
|
+
const config = (0, core_1.specToRecipe)(spec);
|
|
79
|
+
exports.chipRecipe = Object.assign((0, core_1.resolveRecipe)(config), { config });
|
|
80
|
+
exports.default = config;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.chipRecipe = exports.Chip = void 0;
|
|
4
|
+
var chip_1 = require("./chip");
|
|
5
|
+
Object.defineProperty(exports, "Chip", { enumerable: true, get: function () { return chip_1.Chip; } });
|
|
6
|
+
var chip_recipe_1 = require("./chip.recipe");
|
|
7
|
+
Object.defineProperty(exports, "chipRecipe", { enumerable: true, get: function () { return chip_recipe_1.chipRecipe; } });
|
|
@@ -21,7 +21,12 @@ const config = (0, core_1.defineRecipe)({
|
|
|
21
21
|
name: "contextmenu",
|
|
22
22
|
base: `display: contents; font-family: ${tokens_1.contract.font.sans};`,
|
|
23
23
|
globalCss: `
|
|
24
|
-
|
|
24
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
25
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
26
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
27
|
+
inherited the lock, unclickable, hit-testing right through to
|
|
28
|
+
whatever real element sat behind it. */
|
|
29
|
+
.crisp-contextmenu-content { font-family: ${tokens_1.contract.font.sans}; position: fixed; z-index: 70; pointer-events: auto; min-width: 200px; box-sizing: border-box; padding: ${tokens_1.contract.space["1"]}; border-radius: ${tokens_1.contract.radius.xl}; background: ${tokens_1.contract.bgPopover}; box-shadow: ${tokens_1.elevation.floating}; opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
25
30
|
.crisp-contextmenu-item { display: flex; align-items: center; gap: ${tokens_1.contract.space["2"]}; width: 100%; height: ${tokens_1.contract.size.menuRow}; box-sizing: border-box; padding: 0 ${tokens_1.contract.space["2"]}; margin: 0; border: none; border-radius: ${tokens_1.contract.radius.md}; background: none; color: ${tokens_1.contract.fgPrimary}; font-family: inherit; font-size: ${tokens_1.contract.text.lg}; text-align: start; white-space: nowrap; cursor: pointer; }
|
|
26
31
|
.crisp-contextmenu-item svg { flex-shrink: 0; color: ${tokens_1.contract.fgMuted}; }
|
|
27
32
|
.crisp-contextmenu-item:hover { background: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 6%, transparent); }
|
|
@@ -26,9 +26,14 @@ const config = (0, core_1.defineRecipe)({
|
|
|
26
26
|
-webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
27
27
|
`,
|
|
28
28
|
globalCss: `
|
|
29
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
30
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
31
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
32
|
+
inherited the lock, so every item was unclickable, hit-testing right
|
|
33
|
+
through to whatever real element sat behind it. */
|
|
29
34
|
.crisp-menu-content {
|
|
30
35
|
font-family: ${tokens_1.contract.font.sans}; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
31
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: ${tokens_1.contract.space.px};
|
|
36
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: ${tokens_1.contract.space.px};
|
|
32
37
|
min-width: 200px; max-height: 360px; overflow-y: auto; padding: ${tokens_1.contract.space["1"]};
|
|
33
38
|
border-radius: ${tokens_1.contract.radius.xl}; background: ${tokens_1.contract.bgPopover};
|
|
34
39
|
box-shadow: ${tokens_1.elevation.floating};
|
|
@@ -44,9 +44,14 @@ const config = (0, core_1.defineRecipe)({
|
|
|
44
44
|
& .crisp-multiselect-trigger[data-open] .crisp-multiselect-chevron { transform: rotate(180deg); }
|
|
45
45
|
`,
|
|
46
46
|
globalCss: `
|
|
47
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
48
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
49
|
+
tracks), and the portaled listbox is outside Zag's knowledge -- it
|
|
50
|
+
inherited the lock, so every option was unclickable, hit-testing
|
|
51
|
+
right through to whatever real element sat behind it. */
|
|
47
52
|
.crisp-multiselect-listbox {
|
|
48
53
|
font-family: ${tokens_1.contract.font.sans}; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
49
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: ${tokens_1.contract.space.px};
|
|
54
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: ${tokens_1.contract.space.px};
|
|
50
55
|
max-height: 300px; overflow-y: auto; padding: ${tokens_1.contract.space["1"]};
|
|
51
56
|
border-radius: ${tokens_1.contract.radius.xl}; background: ${tokens_1.contract.bgPopover};
|
|
52
57
|
box-shadow: ${tokens_1.elevation.floating};
|
|
@@ -26,7 +26,12 @@ const config = (0, core_1.defineRecipe)({
|
|
|
26
26
|
name: "popover",
|
|
27
27
|
base: `display: contents; font-family: ${tokens_1.contract.font.sans};`,
|
|
28
28
|
globalCss: `
|
|
29
|
-
|
|
29
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
30
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
31
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
32
|
+
inherited the lock, unclickable, hit-testing right through to
|
|
33
|
+
whatever real element sat behind it. */
|
|
34
|
+
.crisp-popover-content { font-family: ${tokens_1.contract.font.sans}; position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; min-width: 200px; max-width: min(360px, 92vw); padding: ${tokens_1.contract.space["1"]}; border-radius: ${tokens_1.contract.radius.xl}; background: ${tokens_1.contract.bgPopover}; color: ${tokens_1.contract.fgPrimary}; box-shadow: ${tokens_1.elevation.floating}; opacity: 1; transform: none; transition: opacity 0.08s ease, transform 0.08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
30
35
|
.crisp-popover-content[data-align="end"] { transform-origin: top right; }
|
|
31
36
|
.crisp-popover-content[data-up] { transform-origin: bottom left; }
|
|
32
37
|
`,
|
|
@@ -44,9 +44,14 @@ const config = (0, core_1.defineRecipe)({
|
|
|
44
44
|
& .crisp-select-trigger[data-open] .crisp-select-chevron { transform: rotate(180deg); }
|
|
45
45
|
`,
|
|
46
46
|
globalCss: `
|
|
47
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
48
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
49
|
+
tracks), and the portaled listbox is outside Zag's knowledge -- it
|
|
50
|
+
inherited the lock, so every option was unclickable, hit-testing
|
|
51
|
+
right through to whatever real element sat behind it. */
|
|
47
52
|
.crisp-select-listbox {
|
|
48
53
|
font-family: ${tokens_1.contract.font.sans}; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
49
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: ${tokens_1.contract.space.px};
|
|
54
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: ${tokens_1.contract.space.px};
|
|
50
55
|
max-height: 280px; overflow-y: auto; padding: ${tokens_1.contract.space["1"]};
|
|
51
56
|
border-radius: ${tokens_1.contract.radius.xl}; background: ${tokens_1.contract.bgPopover};
|
|
52
57
|
box-shadow: ${tokens_1.elevation.floating};
|
package/dist/cjs/index.js
CHANGED
|
@@ -29,6 +29,7 @@ __exportStar(require("./components/button"), exports);
|
|
|
29
29
|
__exportStar(require("./components/callout"), exports);
|
|
30
30
|
__exportStar(require("./components/card"), exports);
|
|
31
31
|
__exportStar(require("./components/checkbox"), exports);
|
|
32
|
+
__exportStar(require("./components/chip"), exports);
|
|
32
33
|
__exportStar(require("./components/columncalc"), exports);
|
|
33
34
|
__exportStar(require("./components/contextmenu"), exports);
|
|
34
35
|
__exportStar(require("./components/datatable"), exports);
|
|
@@ -72,6 +72,19 @@ function RecordPanel({ record, columns, onClose, className, closeLabel = "Close
|
|
|
72
72
|
// both close on the same keypress, since neither knows about the other --
|
|
73
73
|
// none of the five are built on this listener or registered anywhere it
|
|
74
74
|
// can see, only on the shared floating-stack this checks instead.
|
|
75
|
+
//
|
|
76
|
+
// The listener has to run in the CAPTURE phase, not bubble (#376): Menu's
|
|
77
|
+
// own Escape handling is a React onKeyDown on its content div -- a bubble
|
|
78
|
+
// -phase synthetic handler, which fires (and, closing Menu, synchronously
|
|
79
|
+
// unregisters it from the floating stack) BEFORE a bubble-phase listener
|
|
80
|
+
// on `document` ever sees the event. `hasOpenFloatingLayer()` read AFTER
|
|
81
|
+
// that already reflects Menu's own reaction, not the state Escape actually
|
|
82
|
+
// arrived in, so it raced and lost every time -- confirmed by logging the
|
|
83
|
+
// registration order in a real browser, not by reasoning about it. Capture
|
|
84
|
+
// fires top-down, before Menu's bubble handler runs at all, so the check
|
|
85
|
+
// sees the state as it stood when the key was pressed. This mirrors how
|
|
86
|
+
// Zag's own `trackEscapeKeydown` (Dialog/Drawer's Escape handling) already
|
|
87
|
+
// listens on `document` in capture, for the same reason.
|
|
75
88
|
React.useEffect(() => {
|
|
76
89
|
if (!record)
|
|
77
90
|
return;
|
|
@@ -80,8 +93,8 @@ function RecordPanel({ record, columns, onClose, className, closeLabel = "Close
|
|
|
80
93
|
return;
|
|
81
94
|
onClose();
|
|
82
95
|
};
|
|
83
|
-
document.addEventListener("keydown", onKey);
|
|
84
|
-
return () => document.removeEventListener("keydown", onKey);
|
|
96
|
+
document.addEventListener("keydown", onKey, true);
|
|
97
|
+
return () => document.removeEventListener("keydown", onKey, true);
|
|
85
98
|
}, [record, onClose]);
|
|
86
99
|
if (!record)
|
|
87
100
|
return null;
|
package/dist/contextmenu.css
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
2
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
3
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
4
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
5
|
+
inherited the lock, unclickable, hit-testing right through to
|
|
6
|
+
whatever real element sat behind it. */
|
|
7
|
+
.crisp-contextmenu-content { font-family: var(--crisp-font-sans); position: fixed; z-index: 70; pointer-events: auto; min-width: 200px; box-sizing: border-box; padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
3
8
|
.crisp-contextmenu-item { display: flex; align-items: center; gap: var(--crisp-space-2); width: 100%; height: var(--crisp-size-menuRow); box-sizing: border-box; padding: 0 var(--crisp-space-2); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); text-align: start; white-space: nowrap; cursor: pointer; }
|
|
4
9
|
.crisp-contextmenu-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
5
10
|
.crisp-contextmenu-item:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); }
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
@layer crisp-components {
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
4
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
5
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
6
|
+
inherited the lock, unclickable, hit-testing right through to
|
|
7
|
+
whatever real element sat behind it. */
|
|
8
|
+
.crisp-contextmenu-content { font-family: var(--crisp-font-sans); position: fixed; z-index: 70; pointer-events: auto; min-width: 200px; box-sizing: border-box; padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
4
9
|
.crisp-contextmenu-item { display: flex; align-items: center; gap: var(--crisp-space-2); width: 100%; height: var(--crisp-size-menuRow); box-sizing: border-box; padding: 0 var(--crisp-space-2); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); text-align: start; white-space: nowrap; cursor: pointer; }
|
|
5
10
|
.crisp-contextmenu-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
6
11
|
.crisp-contextmenu-item:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Primitive } from "../../core/index.js";
|
|
4
|
+
import { chipRecipe } from "./chip.recipe.js";
|
|
5
|
+
/**
|
|
6
|
+
* A small pill — the same measured chip RecordsTable, RecordPanel and
|
|
7
|
+
* MultiSelect already draw as `.crisp-recordstable-tag`, exported standalone
|
|
8
|
+
* for surfaces that need one without a table or a fixed option set (e.g. a
|
|
9
|
+
* free-text tag list).
|
|
10
|
+
*
|
|
11
|
+
* This ships the measured body only. Attio's removable × on a chip needs a
|
|
12
|
+
* live, populated multi-value editor to measure against, and none was
|
|
13
|
+
* reachable this round (a person's "Email addresses" field was empty on the
|
|
14
|
+
* only record checked, and "Categories" removes via a checkbox toggle, not
|
|
15
|
+
* an inline ×) — so `Chip` has no `onRemove`/remove button yet. Add one once
|
|
16
|
+
* that surface can be measured; don't guess the icon, its hit target, or its
|
|
17
|
+
* spacing from the label.
|
|
18
|
+
*/
|
|
19
|
+
export const Chip = React.forwardRef(({ tone, className, asChild, children, ...props }, ref) => {
|
|
20
|
+
return (_jsx(Primitive.span, { ref: ref, asChild: asChild, className: chipRecipe({ tone, className }), ...props, children: children }));
|
|
21
|
+
});
|
|
22
|
+
Chip.displayName = "Chip";
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { defineSpec, resolveRecipe, specToRecipe } from "../../core/index.js";
|
|
2
|
+
import { contract as c } from "../../tokens/index.js";
|
|
3
|
+
// The same measured pill RecordsTable/RecordPanel/MultiSelect already draw
|
|
4
|
+
// as ".crisp-recordstable-tag" (product/recordstable/recordstable.tag.ts's
|
|
5
|
+
// recordTagCss): 22px tall, `padding: 0 4px`, `border-radius: chip`,
|
|
6
|
+
// 14px/20px at weight 500, and a 1px inset ring in the tone's colour. That
|
|
7
|
+
// export is raw CSS written to be spliced under another component's own
|
|
8
|
+
// `&` root (RecordsTable/RecordPanel nest it inside their own recipe), so it
|
|
9
|
+
// can't be reused verbatim here — Chip's root IS the styled element, not a
|
|
10
|
+
// wrapper around one. The values below are transcribed from recordTagCss,
|
|
11
|
+
// not re-measured; keep the two in sync by hand if either changes.
|
|
12
|
+
const ring = (v, pct) => `inset 0 0 0 1px color-mix(in srgb, ${v} ${pct}%, transparent)`;
|
|
13
|
+
const soft = (v, pct) => `color-mix(in srgb, ${v} ${pct}%, transparent)`;
|
|
14
|
+
const onFg = (v, pct) => `color-mix(in srgb, ${v} ${pct}%, ${c.fgPrimary})`;
|
|
15
|
+
const spec = defineSpec({
|
|
16
|
+
name: "chip",
|
|
17
|
+
base: {
|
|
18
|
+
display: "inline-flex",
|
|
19
|
+
alignItems: "center",
|
|
20
|
+
height: c.size.chip,
|
|
21
|
+
paddingInline: c.space["1"],
|
|
22
|
+
borderRadius: c.radius.chip,
|
|
23
|
+
fontSize: c.text.lg,
|
|
24
|
+
lineHeight: "20px",
|
|
25
|
+
fontWeight: c.weight.medium,
|
|
26
|
+
whiteSpace: "nowrap",
|
|
27
|
+
},
|
|
28
|
+
variants: {
|
|
29
|
+
tone: {
|
|
30
|
+
neutral: {
|
|
31
|
+
background: soft(c.fgPrimary, 6),
|
|
32
|
+
color: soft(c.fgPrimary, 82),
|
|
33
|
+
boxShadow: `inset 0 0 0 1px ${c.borderSubtle}`,
|
|
34
|
+
},
|
|
35
|
+
brand: {
|
|
36
|
+
background: soft(c.bgBrandSolid, 14),
|
|
37
|
+
color: onFg(c.bgBrandSolid, 82),
|
|
38
|
+
boxShadow: ring(c.bgBrandSolid, 30),
|
|
39
|
+
},
|
|
40
|
+
success: {
|
|
41
|
+
background: soft(c.bgSuccess, 16),
|
|
42
|
+
color: onFg(c.bgSuccess, 78),
|
|
43
|
+
boxShadow: ring(c.bgSuccess, 30),
|
|
44
|
+
},
|
|
45
|
+
warning: {
|
|
46
|
+
background: soft(c.bgWarning, 18),
|
|
47
|
+
color: onFg(c.bgWarning, 82),
|
|
48
|
+
boxShadow: ring(c.bgWarning, 30),
|
|
49
|
+
},
|
|
50
|
+
danger: {
|
|
51
|
+
background: soft(c.bgDanger, 15),
|
|
52
|
+
color: onFg(c.bgDanger, 80),
|
|
53
|
+
boxShadow: ring(c.bgDanger, 30),
|
|
54
|
+
},
|
|
55
|
+
purple: {
|
|
56
|
+
background: soft(c.bgPurple, 16),
|
|
57
|
+
color: onFg(c.bgPurple, 80),
|
|
58
|
+
boxShadow: ring(c.bgPurple, 30),
|
|
59
|
+
},
|
|
60
|
+
cyan: {
|
|
61
|
+
background: soft(c.bgCyan, 18),
|
|
62
|
+
color: onFg(c.bgCyan, 82),
|
|
63
|
+
boxShadow: ring(c.bgCyan, 30),
|
|
64
|
+
},
|
|
65
|
+
orange: {
|
|
66
|
+
background: soft(c.bgOrange, 16),
|
|
67
|
+
color: onFg(c.bgOrange, 82),
|
|
68
|
+
boxShadow: ring(c.bgOrange, 30),
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
defaultVariants: { tone: "neutral" },
|
|
73
|
+
});
|
|
74
|
+
const config = specToRecipe(spec);
|
|
75
|
+
export const chipRecipe = Object.assign(resolveRecipe(config), { config });
|
|
76
|
+
export { spec };
|
|
77
|
+
export default config;
|
|
@@ -18,7 +18,12 @@ const config = defineRecipe({
|
|
|
18
18
|
name: "contextmenu",
|
|
19
19
|
base: `display: contents; font-family: ${c.font.sans};`,
|
|
20
20
|
globalCss: `
|
|
21
|
-
|
|
21
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
22
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
23
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
24
|
+
inherited the lock, unclickable, hit-testing right through to
|
|
25
|
+
whatever real element sat behind it. */
|
|
26
|
+
.crisp-contextmenu-content { font-family: ${c.font.sans}; position: fixed; z-index: 70; pointer-events: auto; min-width: 200px; box-sizing: border-box; padding: ${c.space["1"]}; border-radius: ${c.radius.xl}; background: ${c.bgPopover}; box-shadow: ${e.floating}; opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
22
27
|
.crisp-contextmenu-item { display: flex; align-items: center; gap: ${c.space["2"]}; width: 100%; height: ${c.size.menuRow}; box-sizing: border-box; padding: 0 ${c.space["2"]}; margin: 0; border: none; border-radius: ${c.radius.md}; background: none; color: ${c.fgPrimary}; font-family: inherit; font-size: ${c.text.lg}; text-align: start; white-space: nowrap; cursor: pointer; }
|
|
23
28
|
.crisp-contextmenu-item svg { flex-shrink: 0; color: ${c.fgMuted}; }
|
|
24
29
|
.crisp-contextmenu-item:hover { background: color-mix(in srgb, ${c.fgPrimary} 6%, transparent); }
|
|
@@ -23,9 +23,14 @@ const config = defineRecipe({
|
|
|
23
23
|
-webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
24
24
|
`,
|
|
25
25
|
globalCss: `
|
|
26
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
27
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
28
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
29
|
+
inherited the lock, so every item was unclickable, hit-testing right
|
|
30
|
+
through to whatever real element sat behind it. */
|
|
26
31
|
.crisp-menu-content {
|
|
27
32
|
font-family: ${c.font.sans}; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
28
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: ${c.space.px};
|
|
33
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: ${c.space.px};
|
|
29
34
|
min-width: 200px; max-height: 360px; overflow-y: auto; padding: ${c.space["1"]};
|
|
30
35
|
border-radius: ${c.radius.xl}; background: ${c.bgPopover};
|
|
31
36
|
box-shadow: ${e.floating};
|
|
@@ -41,9 +41,14 @@ const config = defineRecipe({
|
|
|
41
41
|
& .crisp-multiselect-trigger[data-open] .crisp-multiselect-chevron { transform: rotate(180deg); }
|
|
42
42
|
`,
|
|
43
43
|
globalCss: `
|
|
44
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
45
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
46
|
+
tracks), and the portaled listbox is outside Zag's knowledge -- it
|
|
47
|
+
inherited the lock, so every option was unclickable, hit-testing
|
|
48
|
+
right through to whatever real element sat behind it. */
|
|
44
49
|
.crisp-multiselect-listbox {
|
|
45
50
|
font-family: ${c.font.sans}; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
46
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: ${c.space.px};
|
|
51
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: ${c.space.px};
|
|
47
52
|
max-height: 300px; overflow-y: auto; padding: ${c.space["1"]};
|
|
48
53
|
border-radius: ${c.radius.xl}; background: ${c.bgPopover};
|
|
49
54
|
box-shadow: ${e.floating};
|
|
@@ -23,7 +23,12 @@ const config = defineRecipe({
|
|
|
23
23
|
name: "popover",
|
|
24
24
|
base: `display: contents; font-family: ${c.font.sans};`,
|
|
25
25
|
globalCss: `
|
|
26
|
-
|
|
26
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
27
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
28
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
29
|
+
inherited the lock, unclickable, hit-testing right through to
|
|
30
|
+
whatever real element sat behind it. */
|
|
31
|
+
.crisp-popover-content { font-family: ${c.font.sans}; position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; min-width: 200px; max-width: min(360px, 92vw); padding: ${c.space["1"]}; border-radius: ${c.radius.xl}; background: ${c.bgPopover}; color: ${c.fgPrimary}; box-shadow: ${e.floating}; opacity: 1; transform: none; transition: opacity 0.08s ease, transform 0.08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
27
32
|
.crisp-popover-content[data-align="end"] { transform-origin: top right; }
|
|
28
33
|
.crisp-popover-content[data-up] { transform-origin: bottom left; }
|
|
29
34
|
`,
|
|
@@ -41,9 +41,14 @@ const config = defineRecipe({
|
|
|
41
41
|
& .crisp-select-trigger[data-open] .crisp-select-chevron { transform: rotate(180deg); }
|
|
42
42
|
`,
|
|
43
43
|
globalCss: `
|
|
44
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
45
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
46
|
+
tracks), and the portaled listbox is outside Zag's knowledge -- it
|
|
47
|
+
inherited the lock, so every option was unclickable, hit-testing
|
|
48
|
+
right through to whatever real element sat behind it. */
|
|
44
49
|
.crisp-select-listbox {
|
|
45
50
|
font-family: ${c.font.sans}; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
46
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: ${c.space.px};
|
|
51
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: ${c.space.px};
|
|
47
52
|
max-height: 280px; overflow-y: auto; padding: ${c.space["1"]};
|
|
48
53
|
border-radius: ${c.radius.xl}; background: ${c.bgPopover};
|
|
49
54
|
box-shadow: ${e.floating};
|
package/dist/esm/index.js
CHANGED
|
@@ -13,6 +13,7 @@ export * from "./components/button/index.js";
|
|
|
13
13
|
export * from "./components/callout/index.js";
|
|
14
14
|
export * from "./components/card/index.js";
|
|
15
15
|
export * from "./components/checkbox/index.js";
|
|
16
|
+
export * from "./components/chip/index.js";
|
|
16
17
|
export * from "./components/columncalc/index.js";
|
|
17
18
|
export * from "./components/contextmenu/index.js";
|
|
18
19
|
export * from "./components/datatable/index.js";
|
|
@@ -36,6 +36,19 @@ export function RecordPanel({ record, columns, onClose, className, closeLabel =
|
|
|
36
36
|
// both close on the same keypress, since neither knows about the other --
|
|
37
37
|
// none of the five are built on this listener or registered anywhere it
|
|
38
38
|
// can see, only on the shared floating-stack this checks instead.
|
|
39
|
+
//
|
|
40
|
+
// The listener has to run in the CAPTURE phase, not bubble (#376): Menu's
|
|
41
|
+
// own Escape handling is a React onKeyDown on its content div -- a bubble
|
|
42
|
+
// -phase synthetic handler, which fires (and, closing Menu, synchronously
|
|
43
|
+
// unregisters it from the floating stack) BEFORE a bubble-phase listener
|
|
44
|
+
// on `document` ever sees the event. `hasOpenFloatingLayer()` read AFTER
|
|
45
|
+
// that already reflects Menu's own reaction, not the state Escape actually
|
|
46
|
+
// arrived in, so it raced and lost every time -- confirmed by logging the
|
|
47
|
+
// registration order in a real browser, not by reasoning about it. Capture
|
|
48
|
+
// fires top-down, before Menu's bubble handler runs at all, so the check
|
|
49
|
+
// sees the state as it stood when the key was pressed. This mirrors how
|
|
50
|
+
// Zag's own `trackEscapeKeydown` (Dialog/Drawer's Escape handling) already
|
|
51
|
+
// listens on `document` in capture, for the same reason.
|
|
39
52
|
React.useEffect(() => {
|
|
40
53
|
if (!record)
|
|
41
54
|
return;
|
|
@@ -44,8 +57,8 @@ export function RecordPanel({ record, columns, onClose, className, closeLabel =
|
|
|
44
57
|
return;
|
|
45
58
|
onClose();
|
|
46
59
|
};
|
|
47
|
-
document.addEventListener("keydown", onKey);
|
|
48
|
-
return () => document.removeEventListener("keydown", onKey);
|
|
60
|
+
document.addEventListener("keydown", onKey, true);
|
|
61
|
+
return () => document.removeEventListener("keydown", onKey, true);
|
|
49
62
|
}, [record, onClose]);
|
|
50
63
|
if (!record)
|
|
51
64
|
return null;
|
package/dist/menu.css
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
|
|
2
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
3
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
4
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
5
|
+
inherited the lock, so every item was unclickable, hit-testing right
|
|
6
|
+
through to whatever real element sat behind it. */
|
|
2
7
|
.crisp-menu-content {
|
|
3
8
|
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
4
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
9
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
5
10
|
min-width: 200px; max-height: 360px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
6
11
|
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
7
12
|
box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
|
package/dist/menu.layered.css
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
@layer crisp-components {
|
|
2
2
|
|
|
3
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
4
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
5
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
6
|
+
inherited the lock, so every item was unclickable, hit-testing right
|
|
7
|
+
through to whatever real element sat behind it. */
|
|
3
8
|
.crisp-menu-content {
|
|
4
9
|
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
5
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
10
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
6
11
|
min-width: 200px; max-height: 360px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
7
12
|
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
8
13
|
box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
|
package/dist/multiselect.css
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
|
|
2
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
3
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
4
|
+
tracks), and the portaled listbox is outside Zag's knowledge -- it
|
|
5
|
+
inherited the lock, so every option was unclickable, hit-testing
|
|
6
|
+
right through to whatever real element sat behind it. */
|
|
2
7
|
.crisp-multiselect-listbox {
|
|
3
8
|
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
4
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
9
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
5
10
|
max-height: 300px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
6
11
|
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
7
12
|
box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
@layer crisp-components {
|
|
2
2
|
|
|
3
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
4
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
5
|
+
tracks), and the portaled listbox is outside Zag's knowledge -- it
|
|
6
|
+
inherited the lock, so every option was unclickable, hit-testing
|
|
7
|
+
right through to whatever real element sat behind it. */
|
|
3
8
|
.crisp-multiselect-listbox {
|
|
4
9
|
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
5
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
10
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
6
11
|
max-height: 300px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
7
12
|
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
8
13
|
box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
|
package/dist/popover.css
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
2
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
3
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
4
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
5
|
+
inherited the lock, unclickable, hit-testing right through to
|
|
6
|
+
whatever real element sat behind it. */
|
|
7
|
+
.crisp-popover-content { font-family: var(--crisp-font-sans); position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; min-width: 200px; max-width: min(360px, 92vw); padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); color: var(--crisp-fg-primary); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); opacity: 1; transform: none; transition: opacity 0.08s ease, transform 0.08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
3
8
|
.crisp-popover-content[data-align="end"] { transform-origin: top right; }
|
|
4
9
|
.crisp-popover-content[data-up] { transform-origin: bottom left; }
|
|
5
10
|
|
package/dist/popover.layered.css
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
@layer crisp-components {
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
4
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
5
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
6
|
+
inherited the lock, unclickable, hit-testing right through to
|
|
7
|
+
whatever real element sat behind it. */
|
|
8
|
+
.crisp-popover-content { font-family: var(--crisp-font-sans); position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; min-width: 200px; max-width: min(360px, 92vw); padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); color: var(--crisp-fg-primary); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); opacity: 1; transform: none; transition: opacity 0.08s ease, transform 0.08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
4
9
|
.crisp-popover-content[data-align="end"] { transform-origin: top right; }
|
|
5
10
|
.crisp-popover-content[data-up] { transform-origin: bottom left; }
|
|
6
11
|
|
package/dist/select.css
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
|
|
2
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
3
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
4
|
+
tracks), and the portaled listbox is outside Zag's knowledge -- it
|
|
5
|
+
inherited the lock, so every option was unclickable, hit-testing
|
|
6
|
+
right through to whatever real element sat behind it. */
|
|
2
7
|
.crisp-select-listbox {
|
|
3
8
|
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
4
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
9
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
5
10
|
max-height: 280px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
6
11
|
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
7
12
|
box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
|
package/dist/select.layered.css
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
@layer crisp-components {
|
|
2
2
|
|
|
3
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
4
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
5
|
+
tracks), and the portaled listbox is outside Zag's knowledge -- it
|
|
6
|
+
inherited the lock, so every option was unclickable, hit-testing
|
|
7
|
+
right through to whatever real element sat behind it. */
|
|
3
8
|
.crisp-select-listbox {
|
|
4
9
|
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
5
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
10
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
6
11
|
max-height: 280px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
7
12
|
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
8
13
|
box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
|
package/dist/styles.css
CHANGED
|
@@ -428,6 +428,34 @@
|
|
|
428
428
|
}
|
|
429
429
|
}
|
|
430
430
|
|
|
431
|
+
.crisp-chip {
|
|
432
|
+
display: inline-flex; align-items: center; height: var(--crisp-size-chip); 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;
|
|
433
|
+
}
|
|
434
|
+
.crisp-chip--tone_neutral {
|
|
435
|
+
background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle);
|
|
436
|
+
}
|
|
437
|
+
.crisp-chip--tone_brand {
|
|
438
|
+
background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-brand-solid) 30%, transparent);
|
|
439
|
+
}
|
|
440
|
+
.crisp-chip--tone_success {
|
|
441
|
+
background: color-mix(in srgb, var(--crisp-bg-success) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-success) 78%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-success) 30%, transparent);
|
|
442
|
+
}
|
|
443
|
+
.crisp-chip--tone_warning {
|
|
444
|
+
background: color-mix(in srgb, var(--crisp-bg-warning) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-warning) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-warning) 30%, transparent);
|
|
445
|
+
}
|
|
446
|
+
.crisp-chip--tone_danger {
|
|
447
|
+
background: color-mix(in srgb, var(--crisp-bg-danger) 15%, transparent); color: color-mix(in srgb, var(--crisp-bg-danger) 80%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-danger) 30%, transparent);
|
|
448
|
+
}
|
|
449
|
+
.crisp-chip--tone_purple {
|
|
450
|
+
background: color-mix(in srgb, var(--crisp-bg-purple) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-purple) 80%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-purple) 30%, transparent);
|
|
451
|
+
}
|
|
452
|
+
.crisp-chip--tone_cyan {
|
|
453
|
+
background: color-mix(in srgb, var(--crisp-bg-cyan) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-cyan) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-cyan) 30%, transparent);
|
|
454
|
+
}
|
|
455
|
+
.crisp-chip--tone_orange {
|
|
456
|
+
background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-orange) 30%, transparent);
|
|
457
|
+
}
|
|
458
|
+
|
|
431
459
|
.crisp-columncalc {
|
|
432
460
|
display: flex; align-items: stretch; width: 100%; height: 100%; font-family: var(--crisp-font-sans); /* Menu wraps its trigger in a flex div that sizes to content, which would shrink the button back to its text. Make the wrapper fill too, so the whole cell stays clickable. */
|
|
433
461
|
& .crisp-menu { width: 100%; height: 100%; }
|
|
@@ -459,7 +487,12 @@
|
|
|
459
487
|
}
|
|
460
488
|
|
|
461
489
|
|
|
462
|
-
|
|
490
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
491
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
492
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
493
|
+
inherited the lock, unclickable, hit-testing right through to
|
|
494
|
+
whatever real element sat behind it. */
|
|
495
|
+
.crisp-contextmenu-content { font-family: var(--crisp-font-sans); position: fixed; z-index: 70; pointer-events: auto; min-width: 200px; box-sizing: border-box; padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
463
496
|
.crisp-contextmenu-item { display: flex; align-items: center; gap: var(--crisp-space-2); width: 100%; height: var(--crisp-size-menuRow); box-sizing: border-box; padding: 0 var(--crisp-space-2); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); text-align: start; white-space: nowrap; cursor: pointer; }
|
|
464
497
|
.crisp-contextmenu-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
465
498
|
.crisp-contextmenu-item:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); }
|
|
@@ -985,9 +1018,14 @@
|
|
|
985
1018
|
}
|
|
986
1019
|
|
|
987
1020
|
|
|
1021
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
1022
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
1023
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
1024
|
+
inherited the lock, so every item was unclickable, hit-testing right
|
|
1025
|
+
through to whatever real element sat behind it. */
|
|
988
1026
|
.crisp-menu-content {
|
|
989
1027
|
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
990
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
1028
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
991
1029
|
min-width: 200px; max-height: 360px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
992
1030
|
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
993
1031
|
box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
|
|
@@ -1031,9 +1069,14 @@
|
|
|
1031
1069
|
}
|
|
1032
1070
|
|
|
1033
1071
|
|
|
1072
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
1073
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
1074
|
+
tracks), and the portaled listbox is outside Zag's knowledge -- it
|
|
1075
|
+
inherited the lock, so every option was unclickable, hit-testing
|
|
1076
|
+
right through to whatever real element sat behind it. */
|
|
1034
1077
|
.crisp-multiselect-listbox {
|
|
1035
1078
|
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
1036
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
1079
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
1037
1080
|
max-height: 300px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
1038
1081
|
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
1039
1082
|
box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
|
|
@@ -1095,7 +1138,12 @@
|
|
|
1095
1138
|
}
|
|
1096
1139
|
|
|
1097
1140
|
|
|
1098
|
-
|
|
1141
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
1142
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
1143
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
1144
|
+
inherited the lock, unclickable, hit-testing right through to
|
|
1145
|
+
whatever real element sat behind it. */
|
|
1146
|
+
.crisp-popover-content { font-family: var(--crisp-font-sans); position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; min-width: 200px; max-width: min(360px, 92vw); padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); color: var(--crisp-fg-primary); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); opacity: 1; transform: none; transition: opacity 0.08s ease, transform 0.08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
1099
1147
|
.crisp-popover-content[data-align="end"] { transform-origin: top right; }
|
|
1100
1148
|
.crisp-popover-content[data-up] { transform-origin: bottom left; }
|
|
1101
1149
|
|
|
@@ -1261,9 +1309,14 @@
|
|
|
1261
1309
|
}
|
|
1262
1310
|
|
|
1263
1311
|
|
|
1312
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
1313
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
1314
|
+
tracks), and the portaled listbox is outside Zag's knowledge -- it
|
|
1315
|
+
inherited the lock, so every option was unclickable, hit-testing
|
|
1316
|
+
right through to whatever real element sat behind it. */
|
|
1264
1317
|
.crisp-select-listbox {
|
|
1265
1318
|
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
1266
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
1319
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
1267
1320
|
max-height: 280px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
1268
1321
|
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
1269
1322
|
box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
|
package/dist/styles.layered.css
CHANGED
|
@@ -429,6 +429,34 @@
|
|
|
429
429
|
}
|
|
430
430
|
}
|
|
431
431
|
|
|
432
|
+
.crisp-chip {
|
|
433
|
+
display: inline-flex; align-items: center; height: var(--crisp-size-chip); 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;
|
|
434
|
+
}
|
|
435
|
+
.crisp-chip--tone_neutral {
|
|
436
|
+
background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle);
|
|
437
|
+
}
|
|
438
|
+
.crisp-chip--tone_brand {
|
|
439
|
+
background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-brand-solid) 30%, transparent);
|
|
440
|
+
}
|
|
441
|
+
.crisp-chip--tone_success {
|
|
442
|
+
background: color-mix(in srgb, var(--crisp-bg-success) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-success) 78%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-success) 30%, transparent);
|
|
443
|
+
}
|
|
444
|
+
.crisp-chip--tone_warning {
|
|
445
|
+
background: color-mix(in srgb, var(--crisp-bg-warning) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-warning) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-warning) 30%, transparent);
|
|
446
|
+
}
|
|
447
|
+
.crisp-chip--tone_danger {
|
|
448
|
+
background: color-mix(in srgb, var(--crisp-bg-danger) 15%, transparent); color: color-mix(in srgb, var(--crisp-bg-danger) 80%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-danger) 30%, transparent);
|
|
449
|
+
}
|
|
450
|
+
.crisp-chip--tone_purple {
|
|
451
|
+
background: color-mix(in srgb, var(--crisp-bg-purple) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-purple) 80%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-purple) 30%, transparent);
|
|
452
|
+
}
|
|
453
|
+
.crisp-chip--tone_cyan {
|
|
454
|
+
background: color-mix(in srgb, var(--crisp-bg-cyan) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-cyan) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-cyan) 30%, transparent);
|
|
455
|
+
}
|
|
456
|
+
.crisp-chip--tone_orange {
|
|
457
|
+
background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-orange) 30%, transparent);
|
|
458
|
+
}
|
|
459
|
+
|
|
432
460
|
.crisp-columncalc {
|
|
433
461
|
display: flex; align-items: stretch; width: 100%; height: 100%; font-family: var(--crisp-font-sans); /* Menu wraps its trigger in a flex div that sizes to content, which would shrink the button back to its text. Make the wrapper fill too, so the whole cell stays clickable. */
|
|
434
462
|
& .crisp-menu { width: 100%; height: 100%; }
|
|
@@ -460,7 +488,12 @@
|
|
|
460
488
|
}
|
|
461
489
|
|
|
462
490
|
|
|
463
|
-
|
|
491
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
492
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
493
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
494
|
+
inherited the lock, unclickable, hit-testing right through to
|
|
495
|
+
whatever real element sat behind it. */
|
|
496
|
+
.crisp-contextmenu-content { font-family: var(--crisp-font-sans); position: fixed; z-index: 70; pointer-events: auto; min-width: 200px; box-sizing: border-box; padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
464
497
|
.crisp-contextmenu-item { display: flex; align-items: center; gap: var(--crisp-space-2); width: 100%; height: var(--crisp-size-menuRow); box-sizing: border-box; padding: 0 var(--crisp-space-2); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); text-align: start; white-space: nowrap; cursor: pointer; }
|
|
465
498
|
.crisp-contextmenu-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
466
499
|
.crisp-contextmenu-item:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); }
|
|
@@ -986,9 +1019,14 @@
|
|
|
986
1019
|
}
|
|
987
1020
|
|
|
988
1021
|
|
|
1022
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
1023
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
1024
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
1025
|
+
inherited the lock, so every item was unclickable, hit-testing right
|
|
1026
|
+
through to whatever real element sat behind it. */
|
|
989
1027
|
.crisp-menu-content {
|
|
990
1028
|
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
991
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
1029
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
992
1030
|
min-width: 200px; max-height: 360px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
993
1031
|
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
994
1032
|
box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
|
|
@@ -1032,9 +1070,14 @@
|
|
|
1032
1070
|
}
|
|
1033
1071
|
|
|
1034
1072
|
|
|
1073
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
1074
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
1075
|
+
tracks), and the portaled listbox is outside Zag's knowledge -- it
|
|
1076
|
+
inherited the lock, so every option was unclickable, hit-testing
|
|
1077
|
+
right through to whatever real element sat behind it. */
|
|
1035
1078
|
.crisp-multiselect-listbox {
|
|
1036
1079
|
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
1037
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
1080
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
1038
1081
|
max-height: 300px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
1039
1082
|
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
1040
1083
|
box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
|
|
@@ -1096,7 +1139,12 @@
|
|
|
1096
1139
|
}
|
|
1097
1140
|
|
|
1098
1141
|
|
|
1099
|
-
|
|
1142
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
1143
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
1144
|
+
tracks), and the portaled content is outside Zag's knowledge -- it
|
|
1145
|
+
inherited the lock, unclickable, hit-testing right through to
|
|
1146
|
+
whatever real element sat behind it. */
|
|
1147
|
+
.crisp-popover-content { font-family: var(--crisp-font-sans); position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; min-width: 200px; max-width: min(360px, 92vw); padding: var(--crisp-space-1); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover); color: var(--crisp-fg-primary); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); opacity: 1; transform: none; transition: opacity 0.08s ease, transform 0.08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
|
|
1100
1148
|
.crisp-popover-content[data-align="end"] { transform-origin: top right; }
|
|
1101
1149
|
.crisp-popover-content[data-up] { transform-origin: bottom left; }
|
|
1102
1150
|
|
|
@@ -1262,9 +1310,14 @@
|
|
|
1262
1310
|
}
|
|
1263
1311
|
|
|
1264
1312
|
|
|
1313
|
+
/* pointer-events: auto (#375): a modal Dialog sets pointer-events: none
|
|
1314
|
+
on document.body while open (Zag re-enables it only on layers IT
|
|
1315
|
+
tracks), and the portaled listbox is outside Zag's knowledge -- it
|
|
1316
|
+
inherited the lock, so every option was unclickable, hit-testing
|
|
1317
|
+
right through to whatever real element sat behind it. */
|
|
1265
1318
|
.crisp-select-listbox {
|
|
1266
1319
|
font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
1267
|
-
position: fixed; z-index: 70; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
1320
|
+
position: fixed; z-index: 70; pointer-events: auto; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--crisp-space-px);
|
|
1268
1321
|
max-height: 280px; overflow-y: auto; padding: var(--crisp-space-1);
|
|
1269
1322
|
border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-popover);
|
|
1270
1323
|
box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { VariantProps } from "../../core";
|
|
3
|
+
import { chipRecipe } from "./chip.recipe";
|
|
4
|
+
export type ChipProps = React.ComponentPropsWithoutRef<"span"> & VariantProps<typeof chipRecipe> & {
|
|
5
|
+
asChild?: boolean;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* A small pill — the same measured chip RecordsTable, RecordPanel and
|
|
9
|
+
* MultiSelect already draw as `.crisp-recordstable-tag`, exported standalone
|
|
10
|
+
* for surfaces that need one without a table or a fixed option set (e.g. a
|
|
11
|
+
* free-text tag list).
|
|
12
|
+
*
|
|
13
|
+
* This ships the measured body only. Attio's removable × on a chip needs a
|
|
14
|
+
* live, populated multi-value editor to measure against, and none was
|
|
15
|
+
* reachable this round (a person's "Email addresses" field was empty on the
|
|
16
|
+
* only record checked, and "Categories" removes via a checkbox toggle, not
|
|
17
|
+
* an inline ×) — so `Chip` has no `onRemove`/remove button yet. Add one once
|
|
18
|
+
* that surface can be measured; don't guess the icon, its hit target, or its
|
|
19
|
+
* spacing from the label.
|
|
20
|
+
*/
|
|
21
|
+
export declare const Chip: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & VariantProps<import("../..").RecipeFn<{
|
|
22
|
+
readonly tone: {
|
|
23
|
+
readonly neutral: string;
|
|
24
|
+
readonly brand: string;
|
|
25
|
+
readonly success: string;
|
|
26
|
+
readonly warning: string;
|
|
27
|
+
readonly danger: string;
|
|
28
|
+
readonly purple: string;
|
|
29
|
+
readonly cyan: string;
|
|
30
|
+
readonly orange: string;
|
|
31
|
+
};
|
|
32
|
+
}> & {
|
|
33
|
+
config: import("../..").RecipeConfig<{
|
|
34
|
+
readonly tone: {
|
|
35
|
+
readonly neutral: string;
|
|
36
|
+
readonly brand: string;
|
|
37
|
+
readonly success: string;
|
|
38
|
+
readonly warning: string;
|
|
39
|
+
readonly danger: string;
|
|
40
|
+
readonly purple: string;
|
|
41
|
+
readonly cyan: string;
|
|
42
|
+
readonly orange: string;
|
|
43
|
+
};
|
|
44
|
+
}>;
|
|
45
|
+
}> & {
|
|
46
|
+
asChild?: boolean;
|
|
47
|
+
} & React.RefAttributes<HTMLSpanElement>>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
declare const spec: {
|
|
2
|
+
readonly name: "chip";
|
|
3
|
+
readonly base: {
|
|
4
|
+
readonly display: "inline-flex";
|
|
5
|
+
readonly alignItems: "center";
|
|
6
|
+
readonly height: `var(--${string})`;
|
|
7
|
+
readonly paddingInline: `var(--${string})`;
|
|
8
|
+
readonly borderRadius: `var(--${string})`;
|
|
9
|
+
readonly fontSize: `var(--${string})`;
|
|
10
|
+
readonly lineHeight: "20px";
|
|
11
|
+
readonly fontWeight: `var(--${string})`;
|
|
12
|
+
readonly whiteSpace: "nowrap";
|
|
13
|
+
};
|
|
14
|
+
readonly variants: {
|
|
15
|
+
readonly tone: {
|
|
16
|
+
readonly neutral: {
|
|
17
|
+
readonly background: string;
|
|
18
|
+
readonly color: string;
|
|
19
|
+
readonly boxShadow: `inset 0 0 0 1px var(--${string})`;
|
|
20
|
+
};
|
|
21
|
+
readonly brand: {
|
|
22
|
+
background: string;
|
|
23
|
+
color: string;
|
|
24
|
+
boxShadow: string;
|
|
25
|
+
};
|
|
26
|
+
readonly success: {
|
|
27
|
+
background: string;
|
|
28
|
+
color: string;
|
|
29
|
+
boxShadow: string;
|
|
30
|
+
};
|
|
31
|
+
readonly warning: {
|
|
32
|
+
background: string;
|
|
33
|
+
color: string;
|
|
34
|
+
boxShadow: string;
|
|
35
|
+
};
|
|
36
|
+
readonly danger: {
|
|
37
|
+
background: string;
|
|
38
|
+
color: string;
|
|
39
|
+
boxShadow: string;
|
|
40
|
+
};
|
|
41
|
+
readonly purple: {
|
|
42
|
+
background: string;
|
|
43
|
+
color: string;
|
|
44
|
+
boxShadow: string;
|
|
45
|
+
};
|
|
46
|
+
readonly cyan: {
|
|
47
|
+
background: string;
|
|
48
|
+
color: string;
|
|
49
|
+
boxShadow: string;
|
|
50
|
+
};
|
|
51
|
+
readonly orange: {
|
|
52
|
+
background: string;
|
|
53
|
+
color: string;
|
|
54
|
+
boxShadow: string;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
readonly defaultVariants: {
|
|
59
|
+
readonly tone: "neutral";
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
declare const config: import("../..").RecipeConfig<{
|
|
63
|
+
readonly tone: {
|
|
64
|
+
readonly neutral: string;
|
|
65
|
+
readonly brand: string;
|
|
66
|
+
readonly success: string;
|
|
67
|
+
readonly warning: string;
|
|
68
|
+
readonly danger: string;
|
|
69
|
+
readonly purple: string;
|
|
70
|
+
readonly cyan: string;
|
|
71
|
+
readonly orange: string;
|
|
72
|
+
};
|
|
73
|
+
}>;
|
|
74
|
+
export declare const chipRecipe: import("../..").RecipeFn<{
|
|
75
|
+
readonly tone: {
|
|
76
|
+
readonly neutral: string;
|
|
77
|
+
readonly brand: string;
|
|
78
|
+
readonly success: string;
|
|
79
|
+
readonly warning: string;
|
|
80
|
+
readonly danger: string;
|
|
81
|
+
readonly purple: string;
|
|
82
|
+
readonly cyan: string;
|
|
83
|
+
readonly orange: string;
|
|
84
|
+
};
|
|
85
|
+
}> & {
|
|
86
|
+
config: import("../..").RecipeConfig<{
|
|
87
|
+
readonly tone: {
|
|
88
|
+
readonly neutral: string;
|
|
89
|
+
readonly brand: string;
|
|
90
|
+
readonly success: string;
|
|
91
|
+
readonly warning: string;
|
|
92
|
+
readonly danger: string;
|
|
93
|
+
readonly purple: string;
|
|
94
|
+
readonly cyan: string;
|
|
95
|
+
readonly orange: string;
|
|
96
|
+
};
|
|
97
|
+
}>;
|
|
98
|
+
};
|
|
99
|
+
export { spec };
|
|
100
|
+
export default config;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./components/button";
|
|
|
9
9
|
export * from "./components/callout";
|
|
10
10
|
export * from "./components/card";
|
|
11
11
|
export * from "./components/checkbox";
|
|
12
|
+
export * from "./components/chip";
|
|
12
13
|
export * from "./components/columncalc";
|
|
13
14
|
export * from "./components/contextmenu";
|
|
14
15
|
export * from "./components/datatable";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crisp-ui-kit/crisp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.45.0",
|
|
4
4
|
"description": "A lean React design system, measured pixel-for-pixel from Attio.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -88,6 +88,11 @@
|
|
|
88
88
|
"import": "./dist/esm/components/checkbox/index.js",
|
|
89
89
|
"require": "./dist/cjs/components/checkbox/index.js"
|
|
90
90
|
},
|
|
91
|
+
"./chip": {
|
|
92
|
+
"types": "./dist/types/components/chip/index.d.ts",
|
|
93
|
+
"import": "./dist/esm/components/chip/index.js",
|
|
94
|
+
"require": "./dist/cjs/components/chip/index.js"
|
|
95
|
+
},
|
|
91
96
|
"./columncalc": {
|
|
92
97
|
"types": "./dist/types/components/columncalc/index.d.ts",
|
|
93
98
|
"import": "./dist/esm/components/columncalc/index.js",
|