@crisp-ui-kit/crisp 0.33.0 → 0.33.2
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/README.md +33 -1
- package/dist/appshell.css +1 -4
- package/dist/appshell.layered.css +1 -4
- package/dist/authshell.css +4 -19
- package/dist/authshell.layered.css +4 -19
- package/dist/avatar.css +2 -1
- package/dist/avatar.layered.css +2 -1
- package/dist/board.css +1 -4
- package/dist/board.layered.css +1 -4
- package/dist/breadcrumb.css +0 -1
- package/dist/breadcrumb.layered.css +0 -1
- package/dist/button.css +14 -6
- package/dist/button.layered.css +14 -6
- package/dist/card.css +2 -1
- package/dist/card.layered.css +2 -1
- package/dist/checkbox.css +6 -9
- package/dist/checkbox.layered.css +6 -9
- package/dist/cjs/components/avatar/avatar.recipe.js +38 -19
- package/dist/cjs/components/button/button.recipe.js +109 -18
- package/dist/cjs/components/datatable/datatable.js +14 -2
- package/dist/cjs/components/datatable/datatable.recipe.js +5 -0
- package/dist/cjs/components/switch/switch.recipe.js +48 -18
- package/dist/columncalc.css +2 -6
- package/dist/columncalc.layered.css +2 -6
- package/dist/command.css +9 -11
- package/dist/command.layered.css +9 -11
- package/dist/datatable.css +11 -19
- package/dist/datatable.layered.css +11 -19
- package/dist/datepicker.css +15 -80
- package/dist/datepicker.layered.css +15 -80
- package/dist/datepickerfield.css +3 -18
- package/dist/datepickerfield.layered.css +3 -18
- package/dist/donutchart.css +1 -2
- package/dist/donutchart.layered.css +1 -2
- package/dist/entitycard.css +1 -7
- package/dist/entitycard.layered.css +1 -7
- package/dist/esm/components/avatar/avatar.recipe.js +38 -19
- package/dist/esm/components/button/button.recipe.js +109 -18
- package/dist/esm/components/datatable/datatable.js +14 -2
- package/dist/esm/components/datatable/datatable.recipe.js +5 -0
- package/dist/esm/components/switch/switch.recipe.js +48 -18
- package/dist/fileupload.css +10 -60
- package/dist/fileupload.layered.css +10 -60
- package/dist/inbox.css +1 -7
- package/dist/inbox.layered.css +1 -7
- package/dist/input.css +9 -20
- package/dist/input.layered.css +9 -20
- package/dist/listpage.css +2 -12
- package/dist/listpage.layered.css +2 -12
- package/dist/menu.css +3 -19
- package/dist/menu.layered.css +3 -19
- package/dist/multiselect.css +4 -25
- package/dist/multiselect.layered.css +4 -25
- package/dist/navitem.css +5 -13
- package/dist/navitem.layered.css +5 -13
- package/dist/onboarding.css +1 -8
- package/dist/onboarding.layered.css +1 -8
- package/dist/quantitypicker.css +15 -50
- package/dist/quantitypicker.layered.css +15 -50
- package/dist/radiogroup.css +1 -6
- package/dist/radiogroup.layered.css +1 -6
- package/dist/recordpage.css +2 -10
- package/dist/recordpage.layered.css +2 -10
- package/dist/recordpanel.css +1 -13
- package/dist/recordpanel.layered.css +1 -13
- package/dist/recordstable.css +2 -11
- package/dist/recordstable.layered.css +2 -11
- package/dist/resizablepanel.css +4 -15
- package/dist/resizablepanel.layered.css +4 -15
- package/dist/richtext.css +1 -5
- package/dist/richtext.layered.css +1 -5
- package/dist/select.css +7 -30
- package/dist/select.layered.css +7 -30
- package/dist/settingsshell.css +2 -7
- package/dist/settingsshell.layered.css +2 -7
- package/dist/sidebar.css +23 -28
- package/dist/sidebar.layered.css +23 -28
- package/dist/slider.css +1 -8
- package/dist/slider.layered.css +1 -8
- package/dist/statcard.css +1 -2
- package/dist/statcard.layered.css +1 -2
- package/dist/styles.css +196 -652
- package/dist/styles.layered.css +196 -652
- package/dist/switch.css +1 -5
- package/dist/switch.layered.css +1 -5
- package/dist/table.css +2 -1
- package/dist/table.layered.css +2 -1
- package/dist/tabletoolbar.css +1 -3
- package/dist/tabletoolbar.layered.css +1 -3
- package/dist/tabs.css +1 -5
- package/dist/tabs.layered.css +1 -5
- package/dist/tasklist.css +1 -8
- package/dist/tasklist.layered.css +1 -8
- package/dist/textarea.css +2 -13
- package/dist/textarea.layered.css +2 -13
- package/dist/tooltip.css +2 -1
- package/dist/tooltip.layered.css +2 -1
- package/dist/trialbanner.css +2 -11
- package/dist/trialbanner.layered.css +2 -11
- package/dist/types/components/avatar/avatar.d.ts +30 -30
- package/dist/types/components/avatar/avatar.recipe.d.ts +136 -49
- package/dist/types/components/button/button.d.ts +30 -30
- package/dist/types/components/button/button.recipe.d.ts +193 -45
- package/dist/types/components/datatable/datatable.d.ts +10 -1
- package/dist/types/components/switch/switch.recipe.d.ts +57 -3
- package/dist/viewtoggle.css +3 -9
- package/dist/viewtoggle.layered.css +3 -9
- package/dist/wheelpicker.css +14 -59
- package/dist/wheelpicker.layered.css +14 -59
- package/package.json +1 -1
|
@@ -1,26 +1,99 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buttonRecipe = void 0;
|
|
3
|
+
exports.spec = exports.buttonRecipe = void 0;
|
|
4
4
|
const core_1 = require("../../core");
|
|
5
5
|
const tokens_1 = require("../../tokens");
|
|
6
|
-
const
|
|
6
|
+
const spec = (0, core_1.defineSpec)({
|
|
7
7
|
name: "button",
|
|
8
|
-
base:
|
|
8
|
+
base: {
|
|
9
|
+
display: "inline-flex",
|
|
10
|
+
alignItems: "center",
|
|
11
|
+
justifyContent: "center",
|
|
12
|
+
gap: tokens_1.contract.space["1.5"],
|
|
13
|
+
fontFamily: tokens_1.contract.font.sans,
|
|
14
|
+
fontWeight: tokens_1.contract.weight.medium,
|
|
15
|
+
letterSpacing: "-0.14px",
|
|
16
|
+
lineHeight: "20px",
|
|
17
|
+
whiteSpace: "nowrap",
|
|
18
|
+
border: "none",
|
|
19
|
+
cursor: "pointer",
|
|
20
|
+
transition: "background-color .2s, box-shadow .2s, color .2s",
|
|
21
|
+
},
|
|
22
|
+
parts: [
|
|
23
|
+
{ selector: "&:disabled", decls: { opacity: 0.5, cursor: "not-allowed" } },
|
|
24
|
+
],
|
|
9
25
|
variants: {
|
|
10
26
|
intent: {
|
|
11
|
-
primary:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
27
|
+
primary: {
|
|
28
|
+
decls: {
|
|
29
|
+
background: tokens_1.contract.bgBrandSolid,
|
|
30
|
+
color: tokens_1.contract.fgOnBrand,
|
|
31
|
+
boxShadow: "inset 0 0 0 1px rgba(255,255,255,0.07), 0 2px 4px -2px rgba(38,109,240,0.12), 0 3px 6px -2px rgba(38,109,240,0.08)",
|
|
32
|
+
},
|
|
33
|
+
parts: [
|
|
34
|
+
{ selector: "&:hover", decls: { background: tokens_1.contract.bgBrandSolidPressed } },
|
|
35
|
+
{
|
|
36
|
+
selector: "&:active",
|
|
37
|
+
decls: { background: tokens_1.contract.bgBrandSolidPressed },
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
neutral: {
|
|
42
|
+
decls: {
|
|
43
|
+
background: tokens_1.contract.bgSurface,
|
|
44
|
+
color: tokens_1.contract.fgPrimary,
|
|
45
|
+
boxShadow: tokens_1.elevation.field,
|
|
46
|
+
},
|
|
47
|
+
parts: [{ selector: "&:hover", decls: { background: tokens_1.contract.bgRaised } }],
|
|
48
|
+
},
|
|
49
|
+
danger: {
|
|
50
|
+
decls: {
|
|
51
|
+
background: tokens_1.contract.bgDangerSolid,
|
|
52
|
+
color: tokens_1.contract.fgOnBrand,
|
|
53
|
+
boxShadow: "inset 0 0 0 1px rgba(255,255,255,0.07), 0 2px 4px -2px rgba(186,37,37,0.20), 0 3px 6px -2px rgba(186,37,37,0.12)",
|
|
54
|
+
},
|
|
55
|
+
parts: [
|
|
56
|
+
{ selector: "&:hover", decls: { filter: "brightness(0.96)" } },
|
|
57
|
+
{ selector: "&:active", decls: { filter: "brightness(0.92)" } },
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
ghost: {
|
|
61
|
+
decls: {
|
|
62
|
+
background: "transparent",
|
|
63
|
+
color: tokens_1.contract.fgMuted,
|
|
64
|
+
boxShadow: "none",
|
|
65
|
+
},
|
|
66
|
+
parts: [
|
|
67
|
+
{
|
|
68
|
+
selector: "&:hover",
|
|
69
|
+
decls: { background: tokens_1.contract.bgRaised, color: tokens_1.contract.fgPrimary },
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
},
|
|
15
73
|
},
|
|
16
74
|
size: {
|
|
17
|
-
sm:
|
|
18
|
-
|
|
19
|
-
|
|
75
|
+
sm: {
|
|
76
|
+
height: "24px",
|
|
77
|
+
paddingInline: tokens_1.contract.space["1.5"],
|
|
78
|
+
fontSize: tokens_1.contract.text.md,
|
|
79
|
+
borderRadius: tokens_1.contract.radius.md,
|
|
80
|
+
},
|
|
81
|
+
md: {
|
|
82
|
+
height: "28px",
|
|
83
|
+
paddingInline: tokens_1.contract.space["2"],
|
|
84
|
+
fontSize: tokens_1.contract.text.lg,
|
|
85
|
+
borderRadius: tokens_1.contract.radius.md,
|
|
86
|
+
},
|
|
87
|
+
lg: {
|
|
88
|
+
height: "40px",
|
|
89
|
+
paddingInline: "14px",
|
|
90
|
+
fontSize: tokens_1.contract.text.lg,
|
|
91
|
+
borderRadius: "10px",
|
|
92
|
+
},
|
|
20
93
|
},
|
|
21
94
|
shape: {
|
|
22
|
-
text:
|
|
23
|
-
icon:
|
|
95
|
+
text: {},
|
|
96
|
+
icon: { paddingInline: 0, aspectRatio: "1 / 1" },
|
|
24
97
|
},
|
|
25
98
|
// Opt-in hit-area expansion (crisp/#62): none of sm/md/lg reaches the
|
|
26
99
|
// 44x44 touch-target minimum (Apple HIG / Material), and enlarging the
|
|
@@ -30,8 +103,27 @@ const config = (0, core_1.defineRecipe)({
|
|
|
30
103
|
// Opt-in rather than always-on: an always-on overlay would swallow
|
|
31
104
|
// clicks meant for a neighbour in a toolbar packed tighter than 44px.
|
|
32
105
|
touchTarget: {
|
|
33
|
-
true:
|
|
34
|
-
|
|
106
|
+
true: {
|
|
107
|
+
decls: { position: "relative" },
|
|
108
|
+
parts: [
|
|
109
|
+
{
|
|
110
|
+
slot: "hitArea",
|
|
111
|
+
selector: "&::after",
|
|
112
|
+
decls: {
|
|
113
|
+
content: '""',
|
|
114
|
+
position: "absolute",
|
|
115
|
+
top: "50%",
|
|
116
|
+
left: "50%",
|
|
117
|
+
transform: "translate(-50%, -50%)",
|
|
118
|
+
width: "100%",
|
|
119
|
+
height: "100%",
|
|
120
|
+
minWidth: "44px",
|
|
121
|
+
minHeight: "44px",
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
},
|
|
126
|
+
false: {},
|
|
35
127
|
},
|
|
36
128
|
},
|
|
37
129
|
defaultVariants: {
|
|
@@ -40,9 +132,8 @@ const config = (0, core_1.defineRecipe)({
|
|
|
40
132
|
shape: "text",
|
|
41
133
|
touchTarget: false,
|
|
42
134
|
},
|
|
43
|
-
compoundVariants: [],
|
|
44
|
-
});
|
|
45
|
-
exports.buttonRecipe = Object.assign((0, core_1.resolveRecipe)(config), {
|
|
46
|
-
config,
|
|
47
135
|
});
|
|
136
|
+
exports.spec = spec;
|
|
137
|
+
const config = (0, core_1.specToRecipe)(spec);
|
|
138
|
+
exports.buttonRecipe = Object.assign((0, core_1.resolveRecipe)(config), { config });
|
|
48
139
|
exports.default = config;
|
|
@@ -155,7 +155,7 @@ function renderTyped(col, value, avatarTone, display) {
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
const CHECK_W = 40;
|
|
158
|
-
function DataTable({ columns: columnsProp, data, selectable = false, selectedIds, onSelectionChange, selectAllLabel = "Select all rows", selectRowLabel = (row) => `Select row ${row.id}`, columnMenu = false, onColumnsChange, groupBy, onRowsReorder, error, sort: sortProp, defaultSort, onSortChange, filterable = false, searchPlaceholder = "Search…", searchLabel = "Search table", onEdit, stickyFirst = true, avatarTone = "brand", surface, interactive = false, onRowClick, onAddRow, addRowLabel = "New record", empty = "No results.", showCount = true, countLabel = (shown, total) => shown === total
|
|
158
|
+
function DataTable({ columns: columnsProp, data, selectable = false, selectedIds, onSelectionChange, selectAllLabel = "Select all rows", selectRowLabel = (row) => `Select row ${row.id}`, selectionAnnouncement = (count) => count === 0 ? "Selection cleared" : `${count} selected`, columnMenu = false, onColumnsChange, groupBy, onRowsReorder, error, sort: sortProp, defaultSort, onSortChange, filterable = false, searchPlaceholder = "Search…", searchLabel = "Search table", onEdit, stickyFirst = true, avatarTone = "brand", surface, interactive = false, onRowClick, onAddRow, addRowLabel = "New record", empty = "No results.", showCount = true, countLabel = (shown, total) => shown === total
|
|
159
159
|
? `${total} ${total === 1 ? "row" : "rows"}`
|
|
160
160
|
: `${shown} of ${total}`, toolbar, className, reorderRowLabel = "Reorder row", ...rest }) {
|
|
161
161
|
const [query, setQuery] = React.useState("");
|
|
@@ -234,6 +234,18 @@ function DataTable({ columns: columnsProp, data, selectable = false, selectedIds
|
|
|
234
234
|
if (!selectedIds)
|
|
235
235
|
setInternalSel(next);
|
|
236
236
|
}, [onSelectionChange, selectedIds]);
|
|
237
|
+
// The selection is announced from a region that is part of the table and
|
|
238
|
+
// outlives every selection, because a consumer's own bulk bar (mounted only
|
|
239
|
+
// once something is picked) cannot announce its own arrival (#234).
|
|
240
|
+
// Derived by adjusting state during render rather than in an effect: it
|
|
241
|
+
// must not fire on mount — nobody has selected anything yet — and it has to
|
|
242
|
+
// cover a `selectedIds` change the consumer makes as well as a click here.
|
|
243
|
+
const prevSelectedCount = React.useRef(selected.size);
|
|
244
|
+
const [selectionText, setSelectionText] = React.useState("");
|
|
245
|
+
if (prevSelectedCount.current !== selected.size) {
|
|
246
|
+
prevSelectedCount.current = selected.size;
|
|
247
|
+
setSelectionText(selectionAnnouncement(selected.size));
|
|
248
|
+
}
|
|
237
249
|
const [editing, setEditing] = React.useState(null);
|
|
238
250
|
const [scrolledX, setScrolledX] = React.useState(false);
|
|
239
251
|
// column widths (drag-to-resize) + fixed-layout sizing
|
|
@@ -464,7 +476,7 @@ function DataTable({ columns: columnsProp, data, selectable = false, selectedIds
|
|
|
464
476
|
return dir === "asc" ? ((0, jsx_runtime_1.jsx)(lucide_react_1.ArrowUp, { className: "crisp-datatable-chevron", size: 13, strokeWidth: 2 })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.ArrowDown, { className: "crisp-datatable-chevron", size: 13, strokeWidth: 2 }));
|
|
465
477
|
return ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronsUpDown, { className: "crisp-datatable-chevron", size: 13, strokeWidth: 2 }));
|
|
466
478
|
}
|
|
467
|
-
return ((0, jsx_runtime_1.jsxs)("div", { ref: gridRef, className: (0, datatable_recipe_1.datatableRecipe)({ className }), tabIndex: -1, onKeyDown: onGridKeyDown, ...rest, children: [(filterable || showCount || toolbar || columnMenu) && ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-datatable-toolbar", children: [columnMenu && ((0, jsx_runtime_1.jsxs)(menu_1.Menu, { align: "start", trigger: (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-datatable-viewsettings", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.SlidersHorizontal, { size: 14, strokeWidth: 1.75 }), "View settings"] }), children: [(0, jsx_runtime_1.jsx)("div", { className: "crisp-datatable-group-label", children: "Columns" }), allColumns.map((c) => ((0, jsx_runtime_1.jsxs)(menu_1.MenuItem, { onSelect: () => c.hidden ? showColumn(c.key) : hideColumn(c.key), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Check, { size: 14, strokeWidth: 2, style: { opacity: c.hidden ? 0 : 1 } }), typeof c.header === "string" ? c.header : c.key] }, c.key)))] })), filterable && ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-datatable-search", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Search, { size: 15, strokeWidth: 1.75, "aria-hidden": "true" }), (0, jsx_runtime_1.jsx)("input", { type: "search", placeholder: searchPlaceholder, value: query, onChange: (e) => setQuery(e.target.value), "aria-label": searchLabel })] })), showCount && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-count", children: countLabel(rows.length, data.length) })), toolbar] })), (0, jsx_runtime_1.jsxs)(table_1.Table, { interactive: interactive, surface: surface, style: { minWidth }, scrollProps: {
|
|
479
|
+
return ((0, jsx_runtime_1.jsxs)("div", { ref: gridRef, className: (0, datatable_recipe_1.datatableRecipe)({ className }), tabIndex: -1, onKeyDown: onGridKeyDown, ...rest, children: [(0, jsx_runtime_1.jsx)("div", { className: "crisp-datatable-live", role: "status", "aria-live": "polite", children: selectionText }), (filterable || showCount || toolbar || columnMenu) && ((0, jsx_runtime_1.jsxs)("div", { className: "crisp-datatable-toolbar", children: [columnMenu && ((0, jsx_runtime_1.jsxs)(menu_1.Menu, { align: "start", trigger: (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "crisp-datatable-viewsettings", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.SlidersHorizontal, { size: 14, strokeWidth: 1.75 }), "View settings"] }), children: [(0, jsx_runtime_1.jsx)("div", { className: "crisp-datatable-group-label", children: "Columns" }), allColumns.map((c) => ((0, jsx_runtime_1.jsxs)(menu_1.MenuItem, { onSelect: () => c.hidden ? showColumn(c.key) : hideColumn(c.key), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Check, { size: 14, strokeWidth: 2, style: { opacity: c.hidden ? 0 : 1 } }), typeof c.header === "string" ? c.header : c.key] }, c.key)))] })), filterable && ((0, jsx_runtime_1.jsxs)("span", { className: "crisp-datatable-search", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Search, { size: 15, strokeWidth: 1.75, "aria-hidden": "true" }), (0, jsx_runtime_1.jsx)("input", { type: "search", placeholder: searchPlaceholder, value: query, onChange: (e) => setQuery(e.target.value), "aria-label": searchLabel })] })), showCount && ((0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-count", children: countLabel(rows.length, data.length) })), toolbar] })), (0, jsx_runtime_1.jsxs)(table_1.Table, { interactive: interactive, surface: surface, style: { minWidth }, scrollProps: {
|
|
468
480
|
onScroll: (e) => setScrolledX(e.currentTarget.scrollLeft > 0),
|
|
469
481
|
...(scrolledX ? { "data-scrolled-x": "" } : {}),
|
|
470
482
|
}, children: [(0, jsx_runtime_1.jsxs)("colgroup", { children: [showGrip && (0, jsx_runtime_1.jsx)("col", { style: { width: GRIP_W } }), selectable && (0, jsx_runtime_1.jsx)("col", { style: { width: CHECK_W } }), columns.map((col) => ((0, jsx_runtime_1.jsx)("col", { style: { width: colWidth(col) } }, col.key)))] }), (0, jsx_runtime_1.jsx)(table_1.TableHeader, { children: (0, jsx_runtime_1.jsxs)(table_1.TableRow, { children: [showGrip && ((0, jsx_runtime_1.jsx)(table_1.TableHead, { className: "crisp-datatable-col-grip", ...stickyCol(-2) })), selectable && ((0, jsx_runtime_1.jsx)(table_1.TableHead, { className: "crisp-datatable-col-check", ...stickyCol(-1), children: (0, jsx_runtime_1.jsx)("span", { className: "crisp-datatable-check", children: (0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { "aria-label": selectAllLabel, checked: allSelected, indeterminate: someSelected, onChange: toggleAll }) }) })), columns.map((col, i) => {
|
|
@@ -18,6 +18,11 @@ const config = (0, core_1.defineRecipe)({
|
|
|
18
18
|
& .crisp-datatable-search input:focus { box-shadow: inset 0 0 0 1px ${tokens_1.contract.bgBrandSolid}; }
|
|
19
19
|
& .crisp-datatable-count { margin-inline-start: auto; font-size: ${tokens_1.contract.text.md}; color: ${tokens_1.contract.fgMuted}; }
|
|
20
20
|
/* The header cell has no padding of its own -- the button owns the
|
|
21
|
+
/* announced, never drawn */
|
|
22
|
+
& .crisp-datatable-live {
|
|
23
|
+
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
|
|
24
|
+
overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
|
|
25
|
+
}
|
|
21
26
|
full cell so the whole header is clickable (its own inset is 12px).
|
|
22
27
|
Mirrors the summary-row fix. */
|
|
23
28
|
& th { padding: 0; }
|
|
@@ -1,28 +1,58 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.switchRecipe = void 0;
|
|
3
|
+
exports.spec = exports.switchRecipe = void 0;
|
|
4
4
|
const core_1 = require("../../core");
|
|
5
5
|
const tokens_1 = require("../../tokens");
|
|
6
6
|
// A settings toggle, measured from the live app: a 24×16 pill track that
|
|
7
7
|
// flips from a muted grey to brand blue (#266df0), with a 12px white thumb
|
|
8
8
|
// (2px inset) that slides 8px across. background + transform both animate .2s.
|
|
9
|
-
const
|
|
9
|
+
const spec = (0, core_1.defineSpec)({
|
|
10
10
|
name: "switch",
|
|
11
|
-
base:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
11
|
+
base: {
|
|
12
|
+
display: "inline-flex",
|
|
13
|
+
alignItems: "center",
|
|
14
|
+
flexShrink: 0,
|
|
15
|
+
width: "24px",
|
|
16
|
+
height: "16px",
|
|
17
|
+
padding: 0,
|
|
18
|
+
margin: 0,
|
|
19
|
+
border: "none",
|
|
20
|
+
borderRadius: tokens_1.contract.radius.full,
|
|
21
|
+
background: `color-mix(in srgb, ${tokens_1.contract.fgPrimary} 9%, transparent)`,
|
|
22
|
+
cursor: "pointer",
|
|
23
|
+
transition: "background-color .2s ease",
|
|
24
|
+
WebkitTapHighlightColor: "transparent",
|
|
25
|
+
},
|
|
26
|
+
parts: [
|
|
27
|
+
{
|
|
28
|
+
slot: "thumb",
|
|
29
|
+
selector: "& .crisp-switch-thumb",
|
|
30
|
+
decls: {
|
|
31
|
+
width: "12px",
|
|
32
|
+
height: "12px",
|
|
33
|
+
margin: "0 2px",
|
|
34
|
+
borderRadius: tokens_1.contract.radius.full,
|
|
35
|
+
background: "#fff",
|
|
36
|
+
transition: "transform .2s ease",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{ selector: "&[data-checked]", decls: { background: tokens_1.contract.bgBrandSolid } },
|
|
40
|
+
{
|
|
41
|
+
slot: "thumb",
|
|
42
|
+
selector: "&[data-checked] .crisp-switch-thumb",
|
|
43
|
+
decls: { transform: "translateX(8px)" },
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
selector: "&:focus-visible",
|
|
47
|
+
decls: {
|
|
48
|
+
outline: `2px solid ${tokens_1.contract.bgBrandSolid}`,
|
|
49
|
+
outlineOffset: "2px",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{ selector: "&:disabled", decls: { opacity: 0.5, cursor: "not-allowed" } },
|
|
53
|
+
],
|
|
27
54
|
});
|
|
55
|
+
exports.spec = spec;
|
|
56
|
+
const config = (0, core_1.specToRecipe)(spec);
|
|
57
|
+
exports.switchRecipe = Object.assign((0, core_1.resolveRecipe)(config), { config });
|
|
28
58
|
exports.default = config;
|
package/dist/columncalc.css
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
.crisp-columncalc {
|
|
2
|
-
display: flex; align-items: stretch; width: 100%; height: 100%; font-family: var(--crisp-font-sans);
|
|
3
|
-
/* Menu wraps its trigger in a flex div that sizes to content, which would
|
|
4
|
-
shrink the button back to its text. Make the wrapper fill too, so the
|
|
5
|
-
whole cell stays clickable. */
|
|
2
|
+
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. */
|
|
6
3
|
& .crisp-menu { width: 100%; height: 100%; }
|
|
7
|
-
|
|
8
|
-
leaves the cell's background showing through at the four corners as
|
|
4
|
+
/* No radius: the trigger fills the cell, so rounding its own corners leaves the cell's background showing through at the four corners as
|
|
9
5
|
soon as the hover tint paints. Everything else that fills a grid cell
|
|
10
6
|
agrees -- recordstable-sum-btn, the same summary trigger, declares no
|
|
11
7
|
radius, and datatable-grip and the embedded pickers zero theirs. An 8px
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
@layer crisp-components {
|
|
2
2
|
.crisp-columncalc {
|
|
3
|
-
display: flex; align-items: stretch; width: 100%; height: 100%; font-family: var(--crisp-font-sans);
|
|
4
|
-
/* Menu wraps its trigger in a flex div that sizes to content, which would
|
|
5
|
-
shrink the button back to its text. Make the wrapper fill too, so the
|
|
6
|
-
whole cell stays clickable. */
|
|
3
|
+
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. */
|
|
7
4
|
& .crisp-menu { width: 100%; height: 100%; }
|
|
8
|
-
|
|
9
|
-
leaves the cell's background showing through at the four corners as
|
|
5
|
+
/* No radius: the trigger fills the cell, so rounding its own corners leaves the cell's background showing through at the four corners as
|
|
10
6
|
soon as the hover tint paints. Everything else that fills a grid cell
|
|
11
7
|
agrees -- recordstable-sum-btn, the same summary trigger, declares no
|
|
12
8
|
radius, and datatable-grip and the embedded pickers zero theirs. An 8px
|
package/dist/command.css
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
.crisp-command {
|
|
2
|
-
display: contents; font-family: var(--crisp-font-sans)
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
combobox names the input through it and points the listbox's
|
|
2
|
+
display: contents; font-family: var(--crisp-font-sans) ;
|
|
3
|
+
& .crisp-command-content, & .crisp-command-card { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
|
|
4
|
+
& .crisp-command-backdrop { position: fixed; inset: 0; z-index: 50; background: transparent; }
|
|
5
|
+
& .crisp-command-positioner { position: fixed; inset: 0; z-index: 51; display: flex; align-items: flex-start; justify-content: center; padding: 15vh var(--crisp-space-4) var(--crisp-space-4); }
|
|
6
|
+
& .crisp-command-content { position: relative; display: flex; flex-direction: column; box-sizing: border-box; width: 90vw; max-width: 748px; max-height: 70vh; padding: var(--crisp-space-1); border-radius: var(--crisp-radius-2xl); background: color-mix(in srgb, var(--crisp-bg-overlay-frost) 60%, transparent); backdrop-filter: blur(15px); -webkit-backdrop-filter: blur(15px); box-shadow: 0 8px 28px -6px var(--crisp-shadow-overlay1), 0 18px 88px -4px var(--crisp-shadow-overlay2), 0 0 1px var(--crisp-shadow-overlay3); opacity: 1; transform: scale(1); transition: opacity 0.2s ease, transform 0.2s ease; @starting-style { opacity: 0; transform: scale(0.97); } }
|
|
7
|
+
& .crisp-command-card { display: flex; flex-direction: column; flex: 1; min-height: 0; box-sizing: border-box; border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); box-shadow: 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); overflow: hidden; }
|
|
8
|
+
& .crisp-command-control { display: flex; align-items: center; gap: var(--crisp-space-2-5); height: 52px; flex-shrink: 0; padding: 0 var(--crisp-space-4); border-bottom: 1px solid var(--crisp-border-subtle); color: var(--crisp-fg-muted); }
|
|
9
|
+
& .crisp-command-control svg { flex-shrink: 0; }
|
|
10
|
+
/* The palette's label element. It exists for the assistive tree only: zag's combobox names the input through it and points the listbox's
|
|
12
11
|
aria-labelledby at it, and without it both were unnamed and the reference
|
|
13
12
|
resolved to nothing (#225). Clipped rather than display:none, which would
|
|
14
13
|
take it out of the tree it exists for. */
|
|
@@ -30,7 +29,6 @@
|
|
|
30
29
|
& .crisp-command-footer-action:disabled { opacity: 0.5; cursor: default; }
|
|
31
30
|
& .crisp-command-footer-action-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
32
31
|
& .crisp-command-footer-key { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: rgba(255,255,255,0.22); font-size: var(--crisp-text-xs); }
|
|
33
|
-
|
|
34
32
|
}
|
|
35
33
|
|
|
36
34
|
@media (prefers-reduced-motion: reduce) {
|
package/dist/command.layered.css
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
@layer crisp-components {
|
|
2
2
|
.crisp-command {
|
|
3
|
-
display: contents; font-family: var(--crisp-font-sans)
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
combobox names the input through it and points the listbox's
|
|
3
|
+
display: contents; font-family: var(--crisp-font-sans) ;
|
|
4
|
+
& .crisp-command-content, & .crisp-command-card { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
|
|
5
|
+
& .crisp-command-backdrop { position: fixed; inset: 0; z-index: 50; background: transparent; }
|
|
6
|
+
& .crisp-command-positioner { position: fixed; inset: 0; z-index: 51; display: flex; align-items: flex-start; justify-content: center; padding: 15vh var(--crisp-space-4) var(--crisp-space-4); }
|
|
7
|
+
& .crisp-command-content { position: relative; display: flex; flex-direction: column; box-sizing: border-box; width: 90vw; max-width: 748px; max-height: 70vh; padding: var(--crisp-space-1); border-radius: var(--crisp-radius-2xl); background: color-mix(in srgb, var(--crisp-bg-overlay-frost) 60%, transparent); backdrop-filter: blur(15px); -webkit-backdrop-filter: blur(15px); box-shadow: 0 8px 28px -6px var(--crisp-shadow-overlay1), 0 18px 88px -4px var(--crisp-shadow-overlay2), 0 0 1px var(--crisp-shadow-overlay3); opacity: 1; transform: scale(1); transition: opacity 0.2s ease, transform 0.2s ease; @starting-style { opacity: 0; transform: scale(0.97); } }
|
|
8
|
+
& .crisp-command-card { display: flex; flex-direction: column; flex: 1; min-height: 0; box-sizing: border-box; border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); box-shadow: 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); overflow: hidden; }
|
|
9
|
+
& .crisp-command-control { display: flex; align-items: center; gap: var(--crisp-space-2-5); height: 52px; flex-shrink: 0; padding: 0 var(--crisp-space-4); border-bottom: 1px solid var(--crisp-border-subtle); color: var(--crisp-fg-muted); }
|
|
10
|
+
& .crisp-command-control svg { flex-shrink: 0; }
|
|
11
|
+
/* The palette's label element. It exists for the assistive tree only: zag's combobox names the input through it and points the listbox's
|
|
13
12
|
aria-labelledby at it, and without it both were unnamed and the reference
|
|
14
13
|
resolved to nothing (#225). Clipped rather than display:none, which would
|
|
15
14
|
take it out of the tree it exists for. */
|
|
@@ -31,7 +30,6 @@
|
|
|
31
30
|
& .crisp-command-footer-action:disabled { opacity: 0.5; cursor: default; }
|
|
32
31
|
& .crisp-command-footer-action-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
33
32
|
& .crisp-command-footer-key { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: rgba(255,255,255,0.22); font-size: var(--crisp-text-xs); }
|
|
34
|
-
|
|
35
33
|
}
|
|
36
34
|
|
|
37
35
|
@media (prefers-reduced-motion: reduce) {
|
package/dist/datatable.css
CHANGED
|
@@ -7,30 +7,26 @@
|
|
|
7
7
|
& .crisp-datatable-search input::placeholder { color: var(--crisp-fg-muted); }
|
|
8
8
|
& .crisp-datatable-search input:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
9
9
|
& .crisp-datatable-count { margin-inline-start: auto; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
10
|
-
/* The header cell has no padding of its own -- the button owns the
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
/* The header cell has no padding of its own -- the button owns the /* announced, never drawn */
|
|
11
|
+
& .crisp-datatable-live { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
|
|
12
|
+
full cell so the whole header is clickable (its own inset is 12px). Mirrors the summary-row fix. */
|
|
13
13
|
& th { padding: 0; }
|
|
14
|
-
/* Same wrapper trap as AUTHORING.md Lesson 40 (ColumnCalc's summary trigger):
|
|
14
|
+
/* Same wrapper trap as AUTHORING.md Lesson 40 (ColumnCalc's summary trigger):
|
|
15
15
|
Menu wraps its trigger in a flex div that sizes to its content, so a
|
|
16
16
|
long header grew past the column instead of filling it -- with nothing
|
|
17
|
-
left to squeeze, the label's own ellipsis CSS (below) had no properly
|
|
18
|
-
|
|
19
|
-
it with no "...". Fill the wrapper, scoped to th so Menu's default
|
|
20
|
-
(correct everywhere else) is untouched. */
|
|
17
|
+
left to squeeze, the label's own ellipsis CSS (below) had no properly -sized box to truncate against, and the th's own overflow hard-clipped
|
|
18
|
+
it with no "...". Fill the wrapper, scoped to th so Menu's default (correct everywhere else) is untouched. */
|
|
21
19
|
& th .crisp-menu { width: 100%; height: 100%; }
|
|
22
20
|
& .crisp-datatable-th-inner { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; min-width: 0; height: 100%; }
|
|
23
21
|
& .crisp-datatable-th-inner > svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
24
|
-
/* The summary cell has NO padding of its own -- the calculation trigger
|
|
25
|
-
owns the whole 246x37 area so a click anywhere in the cell opens the
|
|
26
|
-
menu. Zero the cell's inset and let ColumnCalc supply the 12px. */
|
|
22
|
+
/* The summary cell has NO padding of its own -- the calculation trigger owns the whole 246x37 area so a click anywhere in the cell opens the menu. Zero the cell's inset and let ColumnCalc supply the 12px. */
|
|
27
23
|
& tfoot td { padding: 0; }
|
|
28
24
|
/* Group heading row -- a view is grouped under a subtle label with the
|
|
29
25
|
bucket's count beside it. */
|
|
30
|
-
& .crisp-datatable-viewsettings { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s, color .12s; }
|
|
26
|
+
& .crisp-datatable-viewsettings { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s, color .12s; }
|
|
31
27
|
& .crisp-datatable-viewsettings:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
32
28
|
& .crisp-datatable-group-label { padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
33
|
-
|
|
29
|
+
& .crisp-datatable-group { height: var(--crisp-size-menuRow); padding: 0 var(--crisp-space-3); background: var(--crisp-bg-subtle); border-bottom: 1px solid var(--crisp-border-subtle); font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
34
30
|
& .crisp-datatable-group-count { margin-inline-start: var(--crisp-space-1-5); color: var(--crisp-fg-muted); font-variant-numeric: tabular-nums; }
|
|
35
31
|
& .crisp-datatable-th-rename { width: 100%; min-width: 0; height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-1); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); outline: none; }
|
|
36
32
|
& .crisp-datatable-th-rename:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
@@ -84,13 +80,9 @@
|
|
|
84
80
|
& .crisp-datatable-num { font-variant-numeric: tabular-nums; }
|
|
85
81
|
& .crisp-datatable-muted { color: var(--crisp-fg-muted); }
|
|
86
82
|
/* row drag-to-reorder -- a Settings > Objects > Attributes screen measures
|
|
87
|
-
a leading 20px grip column, a 16px grip icon, and the row's own
|
|
88
|
-
hairline doubling as the drop indicator (it tints toward the brand
|
|
89
|
-
colour as the active drop target). The affordance + geometry are
|
|
90
|
-
measured; the drag MECHANISM is crisp's existing house idiom -- HTML5
|
|
83
|
+
a leading 20px grip column, a 16px grip icon, and the row's own hairline doubling as the drop indicator (it tints toward the brand colour as the active drop target). The affordance + geometry are measured; the drag MECHANISM is crisp's existing house idiom -- HTML5
|
|
91
84
|
draggable + dataTransfer, the same one column reorder already uses
|
|
92
|
-
(RecordsTable's reorderColumn) -- not a proprietary
|
|
93
|
-
pointer-events implementation. */
|
|
85
|
+
(RecordsTable's reorderColumn) -- not a proprietary pointer-events implementation. */
|
|
94
86
|
& .crisp-datatable-col-grip { width: 20px; padding: 0; text-align: center; }
|
|
95
87
|
& .crisp-datatable-grip { display: inline-flex; align-items: center; justify-content: center; width: 100%; height: 100%; margin: 0; border: none; border-radius: 0; background: none; font-family: inherit; color: var(--crisp-fg-muted); cursor: grab; }
|
|
96
88
|
& .crisp-datatable-grip:active { cursor: grabbing; }
|
|
@@ -8,30 +8,26 @@
|
|
|
8
8
|
& .crisp-datatable-search input::placeholder { color: var(--crisp-fg-muted); }
|
|
9
9
|
& .crisp-datatable-search input:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
10
10
|
& .crisp-datatable-count { margin-inline-start: auto; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
11
|
-
/* The header cell has no padding of its own -- the button owns the
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
/* The header cell has no padding of its own -- the button owns the /* announced, never drawn */
|
|
12
|
+
& .crisp-datatable-live { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
|
|
13
|
+
full cell so the whole header is clickable (its own inset is 12px). Mirrors the summary-row fix. */
|
|
14
14
|
& th { padding: 0; }
|
|
15
|
-
/* Same wrapper trap as AUTHORING.md Lesson 40 (ColumnCalc's summary trigger):
|
|
15
|
+
/* Same wrapper trap as AUTHORING.md Lesson 40 (ColumnCalc's summary trigger):
|
|
16
16
|
Menu wraps its trigger in a flex div that sizes to its content, so a
|
|
17
17
|
long header grew past the column instead of filling it -- with nothing
|
|
18
|
-
left to squeeze, the label's own ellipsis CSS (below) had no properly
|
|
19
|
-
|
|
20
|
-
it with no "...". Fill the wrapper, scoped to th so Menu's default
|
|
21
|
-
(correct everywhere else) is untouched. */
|
|
18
|
+
left to squeeze, the label's own ellipsis CSS (below) had no properly -sized box to truncate against, and the th's own overflow hard-clipped
|
|
19
|
+
it with no "...". Fill the wrapper, scoped to th so Menu's default (correct everywhere else) is untouched. */
|
|
22
20
|
& th .crisp-menu { width: 100%; height: 100%; }
|
|
23
21
|
& .crisp-datatable-th-inner { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; min-width: 0; height: 100%; }
|
|
24
22
|
& .crisp-datatable-th-inner > svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
25
|
-
/* The summary cell has NO padding of its own -- the calculation trigger
|
|
26
|
-
owns the whole 246x37 area so a click anywhere in the cell opens the
|
|
27
|
-
menu. Zero the cell's inset and let ColumnCalc supply the 12px. */
|
|
23
|
+
/* The summary cell has NO padding of its own -- the calculation trigger owns the whole 246x37 area so a click anywhere in the cell opens the menu. Zero the cell's inset and let ColumnCalc supply the 12px. */
|
|
28
24
|
& tfoot td { padding: 0; }
|
|
29
25
|
/* Group heading row -- a view is grouped under a subtle label with the
|
|
30
26
|
bucket's count beside it. */
|
|
31
|
-
& .crisp-datatable-viewsettings { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s, color .12s; }
|
|
27
|
+
& .crisp-datatable-viewsettings { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s, color .12s; }
|
|
32
28
|
& .crisp-datatable-viewsettings:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
|
|
33
29
|
& .crisp-datatable-group-label { padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
34
|
-
|
|
30
|
+
& .crisp-datatable-group { height: var(--crisp-size-menuRow); padding: 0 var(--crisp-space-3); background: var(--crisp-bg-subtle); border-bottom: 1px solid var(--crisp-border-subtle); font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
35
31
|
& .crisp-datatable-group-count { margin-inline-start: var(--crisp-space-1-5); color: var(--crisp-fg-muted); font-variant-numeric: tabular-nums; }
|
|
36
32
|
& .crisp-datatable-th-rename { width: 100%; min-width: 0; height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-1); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); outline: none; }
|
|
37
33
|
& .crisp-datatable-th-rename:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
@@ -85,13 +81,9 @@
|
|
|
85
81
|
& .crisp-datatable-num { font-variant-numeric: tabular-nums; }
|
|
86
82
|
& .crisp-datatable-muted { color: var(--crisp-fg-muted); }
|
|
87
83
|
/* row drag-to-reorder -- a Settings > Objects > Attributes screen measures
|
|
88
|
-
a leading 20px grip column, a 16px grip icon, and the row's own
|
|
89
|
-
hairline doubling as the drop indicator (it tints toward the brand
|
|
90
|
-
colour as the active drop target). The affordance + geometry are
|
|
91
|
-
measured; the drag MECHANISM is crisp's existing house idiom -- HTML5
|
|
84
|
+
a leading 20px grip column, a 16px grip icon, and the row's own hairline doubling as the drop indicator (it tints toward the brand colour as the active drop target). The affordance + geometry are measured; the drag MECHANISM is crisp's existing house idiom -- HTML5
|
|
92
85
|
draggable + dataTransfer, the same one column reorder already uses
|
|
93
|
-
(RecordsTable's reorderColumn) -- not a proprietary
|
|
94
|
-
pointer-events implementation. */
|
|
86
|
+
(RecordsTable's reorderColumn) -- not a proprietary pointer-events implementation. */
|
|
95
87
|
& .crisp-datatable-col-grip { width: 20px; padding: 0; text-align: center; }
|
|
96
88
|
& .crisp-datatable-grip { display: inline-flex; align-items: center; justify-content: center; width: 100%; height: 100%; margin: 0; border: none; border-radius: 0; background: none; font-family: inherit; color: var(--crisp-fg-muted); cursor: grab; }
|
|
97
89
|
& .crisp-datatable-grip:active { cursor: grabbing; }
|