@crisp-ui-kit/crisp 0.54.10 → 0.55.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/cjs/components/datatable/datatable.js +249 -46
- package/dist/cjs/components/datatable/datatable.recipe.js +24 -0
- package/dist/cjs/components/resizablepanel/resizablepanel.js +10 -1
- package/dist/cjs/components/table/table.js +8 -1
- package/dist/cjs/components/tabletoolbar/tabletoolbar.chrome.js +25 -2
- package/dist/cjs/components/tabletoolbar/tabletoolbar.js +176 -43
- package/dist/cjs/components/tabletoolbar/tabletoolbar.recipe.js +28 -9
- package/dist/cjs/index.js +0 -2
- package/dist/cjs/product/recordpage/column.js +19 -0
- package/dist/cjs/product/recordpage/index.js +6 -1
- package/dist/cjs/product/recordpage/recordpage.js +25 -8
- package/dist/cjs/product/recordpage/test-fixtures.js +55 -0
- package/dist/cjs/product/savedviews/savedviews.recipe.js +13 -11
- package/dist/datatable.css +14 -0
- package/dist/datatable.layered.css +14 -0
- package/dist/esm/components/datatable/datatable.js +250 -47
- package/dist/esm/components/datatable/datatable.recipe.js +24 -0
- package/dist/esm/components/resizablepanel/resizablepanel.js +10 -1
- package/dist/esm/components/table/table.js +8 -1
- package/dist/esm/components/tabletoolbar/tabletoolbar.chrome.js +25 -2
- package/dist/esm/components/tabletoolbar/tabletoolbar.js +177 -44
- package/dist/esm/components/tabletoolbar/tabletoolbar.recipe.js +28 -9
- package/dist/esm/index.js +0 -2
- package/dist/esm/product/recordpage/column.js +16 -0
- package/dist/esm/product/recordpage/index.js +2 -0
- package/dist/esm/product/recordpage/recordpage.js +22 -5
- package/dist/esm/product/recordpage/test-fixtures.js +52 -0
- package/dist/esm/product/savedviews/savedviews.recipe.js +13 -11
- package/dist/savedviews.css +6 -18
- package/dist/savedviews.layered.css +6 -18
- package/dist/styles.css +43 -276
- package/dist/styles.layered.css +43 -276
- package/dist/tabletoolbar.css +23 -3
- package/dist/tabletoolbar.layered.css +23 -3
- package/dist/types/components/datatable/datatable.d.ts +30 -3
- package/dist/types/components/table/table.d.ts +14 -0
- package/dist/types/components/tabletoolbar/tabletoolbar.d.ts +26 -1
- package/dist/types/index.d.ts +0 -2
- package/dist/types/product/recordpage/column.d.ts +112 -0
- package/dist/types/product/recordpage/index.d.ts +2 -0
- package/dist/types/product/recordpage/recordpage.d.ts +1 -1
- package/dist/types/product/recordpage/test-fixtures.d.ts +3 -0
- package/dist/types/product/recordpanel/recordpanel.d.ts +1 -1
- package/package.json +2 -12
- package/dist/cjs/product/recordstable/company-logos.js +0 -29
- package/dist/cjs/product/recordstable/index.js +0 -13
- package/dist/cjs/product/recordstable/recordstable.js +0 -1357
- package/dist/cjs/product/recordstable/recordstable.recipe.js +0 -175
- package/dist/cjs/product/recordstable/recordstable.tag.js +0 -26
- package/dist/cjs/product/taskstable/index.js +0 -7
- package/dist/cjs/product/taskstable/taskstable.js +0 -27
- package/dist/cjs/product/taskstable/taskstable.recipe.js +0 -56
- package/dist/esm/product/recordstable/company-logos.js +0 -26
- package/dist/esm/product/recordstable/index.js +0 -3
- package/dist/esm/product/recordstable/recordstable.js +0 -1317
- package/dist/esm/product/recordstable/recordstable.recipe.js +0 -172
- package/dist/esm/product/recordstable/recordstable.tag.js +0 -23
- package/dist/esm/product/taskstable/index.js +0 -2
- package/dist/esm/product/taskstable/taskstable.js +0 -24
- package/dist/esm/product/taskstable/taskstable.recipe.js +0 -53
- package/dist/recordstable.css +0 -223
- package/dist/recordstable.d.ts +0 -7
- package/dist/recordstable.layered.css +0 -225
- package/dist/taskstable.css +0 -30
- package/dist/taskstable.d.ts +0 -7
- package/dist/taskstable.layered.css +0 -32
- package/dist/types/product/recordstable/company-logos.d.ts +0 -1
- package/dist/types/product/recordstable/index.d.ts +0 -3
- package/dist/types/product/recordstable/recordstable.d.ts +0 -289
- package/dist/types/product/recordstable/recordstable.recipe.d.ts +0 -5
- package/dist/types/product/recordstable/recordstable.tag.d.ts +0 -15
- package/dist/types/product/taskstable/index.d.ts +0 -2
- package/dist/types/product/taskstable/taskstable.d.ts +0 -54
- package/dist/types/product/taskstable/taskstable.recipe.d.ts +0 -3
- /package/dist/cjs/product/{recordstable → recordpage}/editable-field.js +0 -0
- /package/dist/esm/product/{recordstable → recordpage}/editable-field.js +0 -0
- /package/dist/types/product/{recordstable → recordpage}/editable-field.d.ts +0 -0
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
@layer crisp-components {
|
|
2
|
-
.crisp-recordstable {
|
|
3
|
-
box-sizing: border-box; position: relative; display: flex; flex-direction: column; min-height: 0; height: 100%; width: 100%; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
4
|
-
& * { box-sizing: border-box; }
|
|
5
|
-
/* toolbar */
|
|
6
|
-
& .crisp-recordstable-toolbar { display: flex; align-items: center; gap: var(--crisp-space-2); padding: 0 var(--crisp-space-3) var(--crisp-space-2); }
|
|
7
|
-
& .crisp-recordstable-toolbar[data-inline] { padding-bottom: 0; }
|
|
8
|
-
& .crisp-recordstable-search { display: flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); padding: 0 var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); color: var(--crisp-fg-muted); }
|
|
9
|
-
& .crisp-recordstable-search svg { flex-shrink: 0; }
|
|
10
|
-
& .crisp-recordstable-search input { border: none; outline: none; background: transparent; font-family: inherit; font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); width: 180px; }
|
|
11
|
-
& .crisp-recordstable-search input::placeholder { color: var(--crisp-fg-muted); }
|
|
12
|
-
& .crisp-recordstable-tool { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px var(--crisp-border-default); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
|
|
13
|
-
& .crisp-recordstable-tool:hover { background: var(--crisp-bg-raised); }
|
|
14
|
-
& .crisp-recordstable-tool svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
15
|
-
& .crisp-recordstable-tool--active { background: var(--crisp-bg-raised); }
|
|
16
|
-
& .crisp-recordstable-tool--ghost { box-shadow: none; background: color-mix(in srgb, var(--crisp-fg-primary) 3%, transparent); color: var(--crisp-fg-muted); }
|
|
17
|
-
& .crisp-recordstable-tool--ghost:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); }
|
|
18
|
-
& .crisp-recordstable-toolgroup { position: relative; display: inline-flex; }
|
|
19
|
-
& .crisp-recordstable-divider { flex-shrink: 0; width: 1px; height: 20px; background: var(--crisp-border-subtle); }
|
|
20
|
-
& .crisp-recordstable-menu { position: absolute; top: calc(100% + var(--crisp-space-1)); left: 0; z-index: 30; min-width: 232px; 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); display: flex; flex-direction: column; gap: var(--crisp-space-px); transform-origin: top; opacity: 1; transform: none; transition: opacity .13s ease, transform .13s ease; }
|
|
21
|
-
& .crisp-recordstable-menu { @starting-style { opacity: 0; transform: scale(0.96); } }
|
|
22
|
-
& .crisp-recordstable-ctx { z-index: 60; }
|
|
23
|
-
& .crisp-recordstable-th[data-drop] { box-shadow: inset 2px 0 0 var(--crisp-bg-brand-solid); }
|
|
24
|
-
& .crisp-recordstable-th-inner[draggable="true"]:active { cursor: grabbing; }
|
|
25
|
-
& .crisp-recordstable-menu-head { padding: var(--crisp-space-1) var(--crisp-space-2) var(--crisp-space-0-5); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
|
|
26
|
-
& .crisp-recordstable-sortpop { min-width: 480px; overflow: visible; padding: var(--crisp-space-3) var(--crisp-space-1-5); gap: var(--crisp-space-2); }
|
|
27
|
-
& .crisp-recordstable-sort-empty { padding: var(--crisp-space-1) var(--crisp-space-1) var(--crisp-space-2); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
28
|
-
& .crisp-recordstable-sort-row { display: flex; align-items: center; gap: var(--crisp-space-1-5); }
|
|
29
|
-
& .crisp-recordstable-sort-grip { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 28px; flex-shrink: 0; margin-right: calc(-1 * var(--crisp-space-1)); padding: 0; border: none; background: none; color: var(--crisp-fg-muted); cursor: grab; }
|
|
30
|
-
& .crisp-recordstable-sort-grip:active { cursor: grabbing; }
|
|
31
|
-
& .crisp-recordstable-sort-grip:hover { color: var(--crisp-fg-primary); }
|
|
32
|
-
& .crisp-recordstable-sort-optlabel { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
|
|
33
|
-
& .crisp-recordstable-sort-optlabel svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
34
|
-
& .crisp-recordstable-sort-field { flex: 1; min-width: 0; }
|
|
35
|
-
& .crisp-recordstable-sort-dir { width: 136px; flex-shrink: 0; }
|
|
36
|
-
& .crisp-recordstable-sort-field .crisp-select-trigger, & .crisp-recordstable-sort-dir .crisp-select-trigger { height: 28px; padding-right: var(--crisp-space-1); }
|
|
37
|
-
& .crisp-recordstable-sort-remove { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex-shrink: 0; padding: 0; margin: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-muted); cursor: pointer; transition: background-color .12s, color .12s; }
|
|
38
|
-
& .crisp-recordstable-sort-remove:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
39
|
-
& .crisp-recordstable-sort-addrow { display: flex; padding: var(--crisp-space-0-5) 0; }
|
|
40
|
-
& .crisp-recordstable-sort-add { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 28px; padding: 0 var(--crisp-space-2) 0 var(--crisp-space-1-5); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-regular); color: var(--crisp-fg-primary); cursor: pointer; transition: background-color .12s; }
|
|
41
|
-
& .crisp-recordstable-sort-add:hover { background: var(--crisp-bg-raised); }
|
|
42
|
-
& .crisp-recordstable-sort-add svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
43
|
-
& .crisp-recordstable-sort-foot { display: flex; padding: var(--crisp-space-1-5) var(--crisp-space-1) var(--crisp-space-0-5); }
|
|
44
|
-
& .crisp-recordstable-sort-learn { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); font-size: var(--crisp-text-lg); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); text-decoration: none; }
|
|
45
|
-
& .crisp-recordstable-sort-learn svg { flex-shrink: 0; }
|
|
46
|
-
& .crisp-recordstable-sort-learn:hover { color: var(--crisp-fg-primary); }
|
|
47
|
-
& .crisp-recordstable-menu-item { display: flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; height: var(--crisp-size-menuRow); margin: 0; padding: 0 var(--crisp-space-2); border: none; background: none; border-radius: var(--crisp-radius-md); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); text-align: left; text-decoration: none; cursor: pointer; }
|
|
48
|
-
& .crisp-recordstable-menu-item:hover { background: var(--crisp-bg-raised); }
|
|
49
|
-
& .crisp-recordstable-menu-item:disabled { opacity: 0.4; cursor: default; }
|
|
50
|
-
& .crisp-recordstable-menu-item:disabled:hover { background: none; }
|
|
51
|
-
& .crisp-recordstable-menu-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
|
|
52
|
-
& .crisp-recordstable-menu-item[data-on] svg { color: var(--crisp-bg-brand-solid); }
|
|
53
|
-
& .crisp-recordstable-menu-item .crisp-recordstable-menu-check { margin-left: auto; }
|
|
54
|
-
& .crisp-recordstable-menu-input { height: var(--crisp-size-row); margin: var(--crisp-space-0-5); padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); background: var(--crisp-bg-surface); font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); outline: none; }
|
|
55
|
-
& .crisp-recordstable-menu-sep { height: 1px; border: none; background: var(--crisp-border-subtle); margin: var(--crisp-space-0-5) 0; }
|
|
56
|
-
/* #592: the Filter field picker's nested-scope header (back control +
|
|
57
|
-
search, once drilled into a nestedColumns column) and a search
|
|
58
|
-
result's own breadcrumb row ("Team › Twitter follower count", surfaced by the SAME query matching a nested column). menu-back reuses the established 28px icon-only control pattern this file already uses twice (sort-remove, the kebab segment) rather than an independent measurement of Attio's own back arrow. The breadcrumb
|
|
59
|
-
colours ARE measured live: the parent segment muted at the same
|
|
60
|
-
exact color-mix 63% sort-learn above already uses, the
|
|
61
|
-
separator chevron and leaf segment both full fgPrimary (the
|
|
62
|
-
generic menu-item svg rule below defaults every icon to
|
|
63
|
-
fgMuted, so the separator needs its own override to read
|
|
64
|
-
correctly here). */
|
|
65
|
-
& .crisp-recordstable-menu-nesthead { display: flex; align-items: center; gap: var(--crisp-space-1); margin: var(--crisp-space-0-5); }
|
|
66
|
-
& .crisp-recordstable-menu-nesthead .crisp-recordstable-menu-input { flex: 1; margin: 0; }
|
|
67
|
-
& .crisp-recordstable-menu-back { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex-shrink: 0; padding: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-muted); cursor: pointer; }
|
|
68
|
-
& .crisp-recordstable-menu-back:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
69
|
-
& .crisp-recordstable-menu-item--expand { justify-content: space-between; }
|
|
70
|
-
& .crisp-recordstable-menu-item-path { display: inline-flex; align-items: center; gap: 2px; min-width: 0; overflow: hidden; }
|
|
71
|
-
& .crisp-recordstable-menu-item-path-parent { flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; max-width: 100px; color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
|
|
72
|
-
& .crisp-recordstable-menu-item-path-sep { flex-shrink: 0; color: var(--crisp-fg-primary); }
|
|
73
|
-
& .crisp-recordstable-menu-item-path > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
74
|
-
& .crisp-recordstable-menu--up { top: auto; bottom: calc(100% + var(--crisp-space-1)); transform-origin: bottom; }
|
|
75
|
-
& .crisp-recordstable-menu--right { left: auto; right: 0; }
|
|
76
|
-
& .crisp-recordstable-menu--fixed { position: fixed; top: auto; left: auto; z-index: 40; }
|
|
77
|
-
& .crisp-recordstable-menu--hdr { min-width: 200px; }
|
|
78
|
-
& .crisp-recordstable-menu--op { min-width: 0; }
|
|
79
|
-
& .crisp-recordstable-menu-item--danger { color: var(--crisp-bg-danger); }
|
|
80
|
-
& .crisp-recordstable-menu-item--danger svg { color: var(--crisp-bg-danger); }
|
|
81
|
-
& .crisp-recordstable-menu-item--danger:hover { background: color-mix(in srgb, var(--crisp-bg-danger) 10%, transparent); }
|
|
82
|
-
& .crisp-recordstable-menu-check { margin-left: auto; color: var(--crisp-bg-brand-solid); }
|
|
83
|
-
& .crisp-recordstable-fchip { display: inline-flex; align-items: center; height: var(--crisp-size-row); padding-right: var(--crisp-space-1); border-radius: var(--crisp-radius-md); box-shadow: inset 0 0 0 1px var(--crisp-border-default); background: var(--crisp-bg-surface); font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); white-space: nowrap; }
|
|
84
|
-
& .crisp-recordstable-fchip-main { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 100%; margin: 0; padding: 0 var(--crisp-space-1) 0 var(--crisp-space-2); border: none; background: none; font-family: inherit; font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); cursor: pointer; }
|
|
85
|
-
& .crisp-recordstable-fchip-field { font-weight: var(--crisp-weight-medium); }
|
|
86
|
-
& .crisp-recordstable-fchip-op { color: var(--crisp-fg-muted); }
|
|
87
|
-
& .crisp-recordstable-fchip-val { font-weight: var(--crisp-weight-medium); max-width: 140px; overflow: hidden; text-overflow: ellipsis; }
|
|
88
|
-
& .crisp-recordstable-fchip-x { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: none; color: var(--crisp-fg-muted); cursor: pointer; }
|
|
89
|
-
& .crisp-recordstable-fchip-x:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 10%, transparent); color: var(--crisp-fg-primary); }
|
|
90
|
-
& .crisp-recordstable-spacer { flex: 1; }
|
|
91
|
-
& .crisp-recordstable-count { font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
92
|
-
& .crisp-recordstable-new { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); padding: 0 var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-brand-solid); color: var(--crisp-fg-on-brand); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; transition: background-color .12s; }
|
|
93
|
-
& .crisp-recordstable-new:hover { background: var(--crisp-bg-brand-solid-pressed); }
|
|
94
|
-
|
|
95
|
-
/* scroll frame + table */
|
|
96
|
-
& .crisp-recordstable-scroll { flex: 1; min-height: 0; overflow: auto; background: var(--crisp-bg-surface); border-top: 1px solid var(--crisp-border-subtle); scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--crisp-fg-primary) 22%, transparent) transparent; }
|
|
97
|
-
& .crisp-recordstable-scroll::-webkit-scrollbar { width: 10px; height: 10px; }
|
|
98
|
-
& .crisp-recordstable-scroll::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--crisp-fg-primary) 20%, transparent); border-radius: var(--crisp-radius-full); border: 2px solid var(--crisp-bg-surface); background-clip: padding-box; }
|
|
99
|
-
& .crisp-recordstable-scroll::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 34%, transparent); background-clip: padding-box; }
|
|
100
|
-
& .crisp-recordstable-scroll::-webkit-scrollbar-corner { background: transparent; }
|
|
101
|
-
& .crisp-recordstable-table { table-layout: fixed; border-collapse: separate; border-spacing: 0; }
|
|
102
|
-
& .crisp-recordstable-th, & .crisp-recordstable-td { position: relative; height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-2); border-bottom: 1px solid var(--crisp-border-subtle); border-inline-end: 1px solid var(--crisp-border-subtle); text-align: start; white-space: nowrap; overflow: hidden; }
|
|
103
|
-
& .crisp-recordstable-th { position: sticky; top: 0; z-index: 2; padding: 0; height: var(--crisp-size-tableHeader); background: var(--crisp-bg-surface); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); user-select: none; }
|
|
104
|
-
& .crisp-recordstable-th-inner { display: flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; height: 100%; margin: 0; padding: 0 var(--crisp-space-2); border: none; background: none; color: inherit; font: inherit; letter-spacing: inherit; text-align: start; cursor: pointer; }
|
|
105
|
-
& .crisp-recordstable-th-inner svg { flex-shrink: 0; color: color-mix(in srgb, var(--crisp-fg-primary) 45%, transparent); }
|
|
106
|
-
& .crisp-recordstable-th-label { flex: 1; overflow: hidden; text-overflow: ellipsis; }
|
|
107
|
-
& .crisp-recordstable-th-rename { width: 100%; min-width: 0; height: 100%; margin: 0; padding: 0; border: none; outline: none; background: none; color: inherit; font: inherit; letter-spacing: inherit; }
|
|
108
|
-
& .crisp-recordstable-th-rename:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
|
|
109
|
-
& .crisp-recordstable-sort { flex-shrink: 0; opacity: 0.4; transition: opacity .12s; color: color-mix(in srgb, var(--crisp-fg-primary) 45%, transparent); }
|
|
110
|
-
& .crisp-recordstable-th:hover .crisp-recordstable-sort, & .crisp-recordstable-th[data-sorted] .crisp-recordstable-sort { opacity: 1; }
|
|
111
|
-
& .crisp-recordstable-th[data-sorted="desc"] .crisp-recordstable-sort svg { transform: rotate(180deg); }
|
|
112
|
-
|
|
113
|
-
/* column resize handle */
|
|
114
|
-
& .crisp-recordstable-resize { position: absolute; top: 0; inset-inline-end: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
|
|
115
|
-
& .crisp-recordstable-resize::after { content: ""; position: absolute; top: 0; inset-inline-start: 3px; width: 2px; height: 100%; background: var(--crisp-bg-brand-solid); opacity: 0; transition: opacity .12s; }
|
|
116
|
-
& .crisp-recordstable-resize:hover::after, & .crisp-recordstable-resize[data-resizing]::after { opacity: 1; }
|
|
117
|
-
|
|
118
|
-
/* add-column header */
|
|
119
|
-
& .crisp-recordstable-addcol { min-width: 44px; }
|
|
120
|
-
& .crisp-recordstable-addcol button { display: flex; align-items: center; justify-content: center; width: 44px; height: 100%; border: none; background: none; color: var(--crisp-fg-muted); cursor: pointer; }
|
|
121
|
-
& .crisp-recordstable-addcol button:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
122
|
-
|
|
123
|
-
/* cells */
|
|
124
|
-
/* font-weight is explicit because the first cell of each row is a
|
|
125
|
-
th[scope=row] — the record's name is what the row IS — and a th defaults to bold. Measured before the change and unchanged after: 400. */
|
|
126
|
-
& .crisp-recordstable-td { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-regular); color: var(--crisp-fg-primary); background: var(--crisp-bg-surface); cursor: default; }
|
|
127
|
-
& .crisp-recordstable-td--editable { cursor: text; }
|
|
128
|
-
/* keyboard/click cell selection (spreadsheet-style) */
|
|
129
|
-
& .crisp-recordstable-td[data-selected] { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: -2px; border-radius: var(--crisp-radius-sm); z-index: 3; }
|
|
130
|
-
& .crisp-recordstable-scroll:focus { outline: none; }
|
|
131
|
-
/* picker cells (status / date / reference) host a ghost control edge-to-edge */
|
|
132
|
-
& .crisp-recordstable-td--picker { padding: 0; }
|
|
133
|
-
& .crisp-recordstable-td--picker .crisp-select-trigger, & .crisp-recordstable-td--picker .crisp-datepicker-trigger, & .crisp-recordstable-td--picker .crisp-multiselect-trigger { width: 100%; height: 100%; min-height: 0; border-radius: 0; box-shadow: none; padding: 0 var(--crisp-space-2); }
|
|
134
|
-
& .crisp-recordstable-td--picker .crisp-multiselect-trigger:hover { background: none; }
|
|
135
|
-
& .crisp-recordstable-td--picker .crisp-multiselect-trigger[data-open] { box-shadow: inset 0 0 0 1.5px var(--crisp-bg-brand-solid); }
|
|
136
|
-
/* tag cell: one compact clipped line of full chips, no chevron (opens the picker on click) */
|
|
137
|
-
& .crisp-recordstable-td--picker .crisp-multiselect-chips { flex-wrap: nowrap; overflow: hidden; }
|
|
138
|
-
& .crisp-recordstable-td--picker .crisp-multiselect-chips .crisp-recordstable-tag { flex-shrink: 0; max-width: none; }
|
|
139
|
-
& .crisp-recordstable-td--picker .crisp-multiselect-chevron { display: none; }
|
|
140
|
-
& .crisp-recordstable-td--picker .crisp-multiselect-placeholder { color: var(--crisp-fg-muted); }
|
|
141
|
-
/* reference picker: a leading 16px avatar per option, plus a trailing "Create X" row when the consumer supplies one (#449) -- measured live against Attio's own picker (16px circular avatar, 16px plain icon for
|
|
142
|
-
the create row, both sitting in the option's existing 8px gap, no new gap value invented). */
|
|
143
|
-
& .crisp-recordstable-refoption { display: flex; align-items: center; gap: var(--crisp-space-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
144
|
-
& .crisp-recordstable-refoption-avatar { flex-shrink: 0; }
|
|
145
|
-
& .crisp-recordstable-refoption--create { color: var(--crisp-fg-muted); }
|
|
146
|
-
& .crisp-recordstable-status { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
|
|
147
|
-
& .crisp-recordstable-status-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: var(--crisp-radius-full); }
|
|
148
|
-
& .crisp-recordstable-cell { display: flex; align-items: center; gap: var(--crisp-space-2); height: 100%; min-width: 0; }
|
|
149
|
-
& .crisp-recordstable-cell--num { justify-content: flex-end; font-variant-numeric: tabular-nums; }
|
|
150
|
-
& .crisp-recordstable-cell--tags { gap: var(--crisp-space-1); }
|
|
151
|
-
& .crisp-recordstable-tag { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 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; 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); }
|
|
152
|
-
& .crisp-recordstable-tag[data-tone="brand"] { 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); }
|
|
153
|
-
& .crisp-recordstable-tag[data-tone="success"] { 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); }
|
|
154
|
-
& .crisp-recordstable-tag[data-tone="warning"] { 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); }
|
|
155
|
-
& .crisp-recordstable-tag[data-tone="danger"] { 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); }
|
|
156
|
-
& .crisp-recordstable-tag[data-tone="purple"] { 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); }
|
|
157
|
-
& .crisp-recordstable-tag[data-tone="cyan"] { 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); }
|
|
158
|
-
& .crisp-recordstable-tag[data-tone="orange"] { 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); }
|
|
159
|
-
& .crisp-recordstable-muted { color: var(--crisp-fg-muted); }
|
|
160
|
-
& .crisp-recordstable-entity { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; color: var(--crisp-fg-primary); font-weight: var(--crisp-weight-medium); text-decoration: none; }
|
|
161
|
-
& .crisp-recordstable-entity:hover .crisp-recordstable-entity-name { text-decoration: underline; }
|
|
162
|
-
& .crisp-recordstable-entity-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
163
|
-
& button.crisp-recordstable-entity-name--link { margin: 0; padding: 0; border: none; background: none; font: inherit; color: inherit; letter-spacing: inherit; text-align: start; cursor: pointer; max-width: 100%; }
|
|
164
|
-
& .crisp-recordstable-fav { width: var(--crisp-size-icon); height: var(--crisp-size-icon); border-radius: var(--crisp-radius-sm); flex-shrink: 0; object-fit: cover; background: var(--crisp-bg-raised); }
|
|
165
|
-
& .crisp-recordstable-open { position: absolute; inset-inline-end: var(--crisp-space-1); top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-default); color: var(--crisp-fg-muted); font-family: inherit; cursor: pointer; opacity: 0; transition: opacity .12s, background-color .12s; z-index: 3; }
|
|
166
|
-
& .crisp-recordstable-open:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
167
|
-
& tbody tr:hover .crisp-recordstable-open { opacity: 1; }
|
|
168
|
-
& .crisp-recordstable-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
|
|
169
|
-
& .crisp-recordstable-link:hover { text-decoration: underline; }
|
|
170
|
-
/* inline edit input */
|
|
171
|
-
& .crisp-recordstable-edit { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0 var(--crisp-space-2); border: none; outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: -2px; border-radius: var(--crisp-radius-sm); background: var(--crisp-bg-surface); font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); z-index: 5; }
|
|
172
|
-
& .crisp-recordstable-edit--num { text-align: end; font-variant-numeric: tabular-nums; }
|
|
173
|
-
/* selection / hover / sticky */
|
|
174
|
-
& .crisp-recordstable-col-check { width: 40px; min-width: 40px; padding: 0; }
|
|
175
|
-
& .crisp-recordstable-check-inner { display: flex; align-items: center; justify-content: center; height: 100%; }
|
|
176
|
-
& .crisp-recordstable-col-check, & .crisp-recordstable-col-entity { position: sticky; z-index: 3; background: var(--crisp-bg-surface); }
|
|
177
|
-
/* The sticky pin is a LOGICAL offset: with physical `left` these columns were not pinned at all under RTL -- scrolled, they left the viewport entirely (measured: viewport 13..773, check column at x=1333). Nothing in JS measures these, so converting them is safe; the two properties below that have no logical form get an explicit RTL rule rather than being left to point the wrong way. */
|
|
178
|
-
& .crisp-recordstable-col-check { inset-inline-start: 0; }
|
|
179
|
-
& .crisp-recordstable-col-entity { inset-inline-start: 40px; clip-path: inset(0 -38px 0 0); transition: box-shadow .2s ease; }
|
|
180
|
-
[dir="rtl"] & .crisp-recordstable-col-entity { clip-path: inset(0 0 0 -38px); }
|
|
181
|
-
& thead .crisp-recordstable-col-check, & thead .crisp-recordstable-col-entity { z-index: 4; }
|
|
182
|
-
/* soft shadow on the sticky column edge once the grid is scrolled horizontally */
|
|
183
|
-
& .crisp-recordstable-scroll[data-scrolled] .crisp-recordstable-col-entity { box-shadow: 6px 0 16px 4px rgba(0,0,0,0.12); }
|
|
184
|
-
/* box-shadow has no logical form either: the bleed follows the scrolled content, which is the opposite side under RTL. */
|
|
185
|
-
[dir="rtl"] & .crisp-recordstable-scroll[data-scrolled] .crisp-recordstable-col-entity { box-shadow: -6px 0 16px 4px rgba(0,0,0,0.12); }
|
|
186
|
-
/* AI-enriched values carry a purple wash. Measured live: a full-bleed overlay at #9b69ff 4% (== bgPurple), composited OVER whatever row-state background the cell already has, which is why it is an ::after and not a background. */
|
|
187
|
-
& .crisp-recordstable-td[data-enriched]::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: color-mix(in srgb, var(--crisp-bg-purple) 4%, transparent); }
|
|
188
|
-
& tbody tr:hover .crisp-recordstable-td { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-surface)); }
|
|
189
|
-
& tbody tr[data-selected] .crisp-recordstable-td { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 10%, var(--crisp-bg-surface)); }
|
|
190
|
-
& tbody tr[data-selected]:hover .crisp-recordstable-td { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, color-mix(in srgb, var(--crisp-bg-brand-solid) 10%, var(--crisp-bg-surface))); }
|
|
191
|
-
& .crisp-recordstable-th:last-child, & .crisp-recordstable-td:last-child { border-inline-end: none; }
|
|
192
|
-
/* add-row footer */
|
|
193
|
-
& .crisp-recordstable-addrow { display: flex; align-items: center; gap: var(--crisp-space-2); width: 100%; height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-2); border: none; border-top: 1px solid var(--crisp-border-subtle); background: var(--crisp-bg-surface); color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-lg); cursor: pointer; }
|
|
194
|
-
& .crisp-recordstable-addrow:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
195
|
-
/* zero-row empty state — centred in the body region (headers + summary stay) */
|
|
196
|
-
& .crisp-recordstable-empty { display: flex; align-items: center; justify-content: center; min-height: 320px; padding: var(--crisp-space-8) var(--crisp-space-4); }
|
|
197
|
-
/* summary footer — per-column aggregation, sticky to the bottom */
|
|
198
|
-
& .crisp-recordstable-sum { position: sticky; bottom: 0; z-index: 2; height: var(--crisp-size-tableRow); padding: 0; border-top: 1px solid var(--crisp-border-subtle); border-bottom: 1px solid var(--crisp-border-subtle); border-inline-end: 1px solid var(--crisp-border-subtle); background: var(--crisp-bg-surface); }
|
|
199
|
-
& tfoot .crisp-recordstable-col-check, & tfoot .crisp-recordstable-col-entity { position: sticky; bottom: 0; z-index: 3; }
|
|
200
|
-
& .crisp-recordstable-sum:last-child { border-inline-end: none; }
|
|
201
|
-
& .crisp-recordstable-sum-btn { display: flex; align-items: center; justify-content: flex-end; gap: var(--crisp-space-1-5); width: 100%; height: 100%; margin: 0; padding: 0 var(--crisp-space-3); border: none; background: none; color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); cursor: pointer; white-space: nowrap; overflow: hidden; }
|
|
202
|
-
& .crisp-recordstable-sum-btn:hover { background: var(--crisp-bg-raised); }
|
|
203
|
-
& .crisp-recordstable-sum-label { color: color-mix(in srgb, var(--crisp-fg-primary) 45%, transparent); text-transform: capitalize; }
|
|
204
|
-
& .crisp-recordstable-sum-value { color: var(--crisp-fg-primary); font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; }
|
|
205
|
-
& .crisp-recordstable-sumgroup { width: 100%; height: 100%; }
|
|
206
|
-
& .crisp-recordstable-pin { flex-shrink: 0; margin-inline-start: var(--crisp-space-1); color: var(--crisp-bg-warning); fill: color-mix(in srgb, var(--crisp-bg-warning) 35%, transparent); }
|
|
207
|
-
& .crisp-recordstable-sum-btn[data-empty] { opacity: 0; justify-content: flex-start; }
|
|
208
|
-
& .crisp-recordstable-sum-btn[data-empty]:hover { opacity: 1; }
|
|
209
|
-
/* bulk action bar lives in its own component now — see components/bulkbar */
|
|
210
|
-
& .crisp-recordstable-bulk-sep { width: 1px; height: 20px; margin: 0 var(--crisp-space-0-5); background: var(--crisp-border-subtle); }
|
|
211
|
-
& .crisp-recordstable-bulk-close { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-muted); cursor: pointer; }
|
|
212
|
-
& .crisp-recordstable-bulk-close:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
|
|
213
|
-
/* announced, never drawn */
|
|
214
|
-
& .crisp-recordstable-live { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
|
|
215
|
-
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
@media (prefers-reduced-motion: reduce) {
|
|
219
|
-
.crisp-recordstable, .crisp-recordstable * {
|
|
220
|
-
animation-duration: 0.01ms !important;
|
|
221
|
-
animation-iteration-count: 1 !important;
|
|
222
|
-
transition-duration: 0.01ms !important;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
package/dist/taskstable.css
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
.crisp-taskstable {
|
|
2
|
-
display: flex; flex-direction: column; min-height: 0; box-sizing: border-box; font-family: var(--crisp-font-sans); color: var(--crisp-fg-primary); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
3
|
-
& .crisp-taskstable-colhead { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-height: 49px; max-height: 49px; padding: var(--crisp-space-2-5) var(--crisp-space-3); box-shadow: inset 0 -1px 0 var(--crisp-border-subtle); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
|
|
4
|
-
& .crisp-taskstable-colhead-cell { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
|
|
5
|
-
& .crisp-taskstable-row { display: flex; align-items: center; gap: var(--crisp-space-1-5); }
|
|
6
|
-
/* #642: measured live -- title, due date and assignee name are ALL 14px/500 on Attio's own Tasks page. Only -title/-due set their own
|
|
7
|
-
font-size (and only -title its own weight), so an unstyled consumer
|
|
8
|
-
slot (a plain PersonChip/RecordChip name span with no font-size of
|
|
9
|
-
its own) fell through to the browser/body default, 16px/400. Set
|
|
10
|
-
the ambient font here so it cascades to any slot content that
|
|
11
|
-
doesn't override it -- -title/-due's own declarations still apply,
|
|
12
|
-
unchanged, they're just now redundant with this baseline rather than the only source of it. */
|
|
13
|
-
& .crisp-taskstable-cell { display: flex; align-items: center; min-width: 0; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); }
|
|
14
|
-
& .crisp-taskstable-check { appearance: none; -webkit-appearance: none; box-sizing: border-box; flex-shrink: 0; margin: 0; width: 16px; height: 16px; border: none; border-radius: var(--crisp-radius-full); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); cursor: pointer; transition: background-color .12s, box-shadow .12s; }
|
|
15
|
-
& .crisp-taskstable-check:hover { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 30%, transparent); }
|
|
16
|
-
& .crisp-taskstable-check:checked { background: var(--crisp-bg-brand-solid) center / 10px no-repeat; box-shadow: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.5 5 9l4.5-5'/%3E%3C/svg%3E"); }
|
|
17
|
-
& .crisp-taskstable-check:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 1px; }
|
|
18
|
-
& .crisp-taskstable-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
19
|
-
& .crisp-taskstable-due { font-size: var(--crisp-text-lg); color: var(--crisp-fg-muted); white-space: nowrap; }
|
|
20
|
-
& .crisp-taskstable-due[data-overdue] { color: var(--crisp-fg-danger); }
|
|
21
|
-
& .crisp-taskstable-empty { padding: var(--crisp-space-8) var(--crisp-space-4); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
@media (prefers-reduced-motion: reduce) {
|
|
25
|
-
.crisp-taskstable, .crisp-taskstable * {
|
|
26
|
-
animation-duration: 0.01ms !important;
|
|
27
|
-
animation-iteration-count: 1 !important;
|
|
28
|
-
transition-duration: 0.01ms !important;
|
|
29
|
-
}
|
|
30
|
-
}
|
package/dist/taskstable.d.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
@layer crisp-components {
|
|
2
|
-
.crisp-taskstable {
|
|
3
|
-
display: flex; flex-direction: column; min-height: 0; box-sizing: border-box; font-family: var(--crisp-font-sans); color: var(--crisp-fg-primary); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
|
|
4
|
-
& .crisp-taskstable-colhead { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-height: 49px; max-height: 49px; padding: var(--crisp-space-2-5) var(--crisp-space-3); box-shadow: inset 0 -1px 0 var(--crisp-border-subtle); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
|
|
5
|
-
& .crisp-taskstable-colhead-cell { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
|
|
6
|
-
& .crisp-taskstable-row { display: flex; align-items: center; gap: var(--crisp-space-1-5); }
|
|
7
|
-
/* #642: measured live -- title, due date and assignee name are ALL 14px/500 on Attio's own Tasks page. Only -title/-due set their own
|
|
8
|
-
font-size (and only -title its own weight), so an unstyled consumer
|
|
9
|
-
slot (a plain PersonChip/RecordChip name span with no font-size of
|
|
10
|
-
its own) fell through to the browser/body default, 16px/400. Set
|
|
11
|
-
the ambient font here so it cascades to any slot content that
|
|
12
|
-
doesn't override it -- -title/-due's own declarations still apply,
|
|
13
|
-
unchanged, they're just now redundant with this baseline rather than the only source of it. */
|
|
14
|
-
& .crisp-taskstable-cell { display: flex; align-items: center; min-width: 0; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); }
|
|
15
|
-
& .crisp-taskstable-check { appearance: none; -webkit-appearance: none; box-sizing: border-box; flex-shrink: 0; margin: 0; width: 16px; height: 16px; border: none; border-radius: var(--crisp-radius-full); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); cursor: pointer; transition: background-color .12s, box-shadow .12s; }
|
|
16
|
-
& .crisp-taskstable-check:hover { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 30%, transparent); }
|
|
17
|
-
& .crisp-taskstable-check:checked { background: var(--crisp-bg-brand-solid) center / 10px no-repeat; box-shadow: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.5 5 9l4.5-5'/%3E%3C/svg%3E"); }
|
|
18
|
-
& .crisp-taskstable-check:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 1px; }
|
|
19
|
-
& .crisp-taskstable-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
|
|
20
|
-
& .crisp-taskstable-due { font-size: var(--crisp-text-lg); color: var(--crisp-fg-muted); white-space: nowrap; }
|
|
21
|
-
& .crisp-taskstable-due[data-overdue] { color: var(--crisp-fg-danger); }
|
|
22
|
-
& .crisp-taskstable-empty { padding: var(--crisp-space-8) var(--crisp-space-4); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
@media (prefers-reduced-motion: reduce) {
|
|
26
|
-
.crisp-taskstable, .crisp-taskstable * {
|
|
27
|
-
animation-duration: 0.01ms !important;
|
|
28
|
-
animation-iteration-count: 1 !important;
|
|
29
|
-
transition-duration: 0.01ms !important;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const companyLogos: Record<string, string>;
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
export { type EditableOption, editableInputType, useEditableField, } from "./editable-field";
|
|
2
|
-
export { type Column, type ColumnType, defaultColumns, defaultRows, type EntityValue, RecordsTable, type RecordsTableProps, type Row, tagTone, } from "./recordstable";
|
|
3
|
-
export { recordstableRecipe } from "./recordstable.recipe";
|
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { type EmptyStateLearnMore } from "../../components/emptystate";
|
|
3
|
-
import type { EditableOption } from "./editable-field";
|
|
4
|
-
type IconType = React.ComponentType<{
|
|
5
|
-
size?: number;
|
|
6
|
-
strokeWidth?: number;
|
|
7
|
-
}>;
|
|
8
|
-
export declare function isLabelTruncated(el: {
|
|
9
|
-
scrollWidth: number;
|
|
10
|
-
clientWidth: number;
|
|
11
|
-
}): boolean;
|
|
12
|
-
export type ColumnType = "entity" | "text" | "tags" | "number" | "url" | "date" | "currency" | "status" | "reference";
|
|
13
|
-
export type StatusOption = {
|
|
14
|
-
value: string;
|
|
15
|
-
label: string;
|
|
16
|
-
color: string;
|
|
17
|
-
};
|
|
18
|
-
export type ReferenceOption = {
|
|
19
|
-
value: string;
|
|
20
|
-
label: string;
|
|
21
|
-
avatar?: string;
|
|
22
|
-
};
|
|
23
|
-
export type Column = {
|
|
24
|
-
key: string;
|
|
25
|
-
label: string;
|
|
26
|
-
type?: ColumnType;
|
|
27
|
-
/** Mark the column's values as AI-enriched — tints the cells the way
|
|
28
|
-
* enriched values are washed (#9b69ff at 4%). */
|
|
29
|
-
enriched?: boolean;
|
|
30
|
-
icon?: IconType;
|
|
31
|
-
/** This column's values reference another type of record (e.g. a
|
|
32
|
-
* "Primary location" column of Country records). When the header
|
|
33
|
-
* overflows, its `Tooltip` appends this type's icon and name after the
|
|
34
|
-
* label and switches to Attio's second, reference-column tooltip chrome
|
|
35
|
-
* (crisp#580) — distinct from `icon` above (the column's own field-type
|
|
36
|
-
* glyph shown in the header row) and from `refOptions` (the picker's
|
|
37
|
-
* selectable values). Omit for a plain column; the tooltip stays
|
|
38
|
-
* label-only (#534). */
|
|
39
|
-
referencedType?: {
|
|
40
|
-
icon: IconType;
|
|
41
|
-
label: string;
|
|
42
|
-
};
|
|
43
|
-
width?: number;
|
|
44
|
-
/** Currency symbol for `currency` columns (default "$"). */
|
|
45
|
-
symbol?: string;
|
|
46
|
-
/** Choices for a `status` column (each a coloured dot + label). */
|
|
47
|
-
options?: StatusOption[];
|
|
48
|
-
/** Choices for a `reference` column (a searchable record picker). */
|
|
49
|
-
refOptions?: ReferenceOption[];
|
|
50
|
-
/** Adds a trailing "Create {createLabel}" row to the picker (Attio's own
|
|
51
|
-
* always has one) — rendered only when this is provided. Picking it hands
|
|
52
|
-
* back the picker's current search text, e.g. to open a create flow
|
|
53
|
-
* pre-seeded with it. */
|
|
54
|
-
onCreateReference?: (query: string) => void;
|
|
55
|
-
/** The object noun in "Create {createLabel}" (Attio: "Create Person").
|
|
56
|
-
* Only used with `onCreateReference`; defaults to "record". */
|
|
57
|
-
createLabel?: string;
|
|
58
|
-
/**
|
|
59
|
-
* Full custom cell content — an escape hatch for a display crisp can't
|
|
60
|
-
* express via `type` (sign-coloured currency, a maskable amount, a custom
|
|
61
|
-
* badge, …). Precedence is **`render` > `format` > the built-in `type`
|
|
62
|
-
* renderer**: when `render` is set it is the *only* thing drawn in the
|
|
63
|
-
* cell, replacing whatever `type` would normally render.
|
|
64
|
-
*
|
|
65
|
-
* Interaction contract for a `render` column: it keeps every grid chrome —
|
|
66
|
-
* row height, hairlines, padding, hover/selected tint, the cell focus ring,
|
|
67
|
-
* shift-click range select, the right-click row menu — but is **never**
|
|
68
|
-
* inline-editable and never shows a `type` picker (status/reference/date/
|
|
69
|
-
* tags), because crisp has no way to write a value back into custom
|
|
70
|
-
* content. Use `format` instead if the column should stay editable.
|
|
71
|
-
*
|
|
72
|
-
* ⌘C copies `format(value, row)` when the column also has one, otherwise
|
|
73
|
-
* the raw value stringified the same way a plain column would — never a
|
|
74
|
-
* serialization of the rendered node. Sort, filter, and the footer
|
|
75
|
-
* aggregation all read `row[column.key]` directly and never call `render`.
|
|
76
|
-
*/
|
|
77
|
-
render?: (value: unknown, row: Row) => React.ReactNode;
|
|
78
|
-
/**
|
|
79
|
-
* Display-only string transform. Unlike `render`, a `format` column keeps
|
|
80
|
-
* the built-in `type` renderer's chrome (a `currency`/`number` column stays
|
|
81
|
-
* right-aligned in its numeric span; `text`/`url`/`date`/the default case
|
|
82
|
-
* keep their own wrapper) — `format`'s return value simply replaces the
|
|
83
|
-
* text that renderer would otherwise show. `format` fully owns that text,
|
|
84
|
-
* so a `currency` column's `format` should include its own symbol/masking
|
|
85
|
-
* if it wants one (the built-in `$` prefix is skipped once `format` is
|
|
86
|
-
* set). A `format` column stays editable/pickable exactly like a plain
|
|
87
|
-
* `type` column — only `render` disables that.
|
|
88
|
-
*
|
|
89
|
-
* Sort, filter, and the footer aggregation all read the **raw**
|
|
90
|
-
* `row[column.key]` value, never `format`'s output — so a grouped/prefixed
|
|
91
|
-
* currency string still sums and sorts numerically.
|
|
92
|
-
*/
|
|
93
|
-
format?: (value: unknown, row: Row) => string;
|
|
94
|
-
/**
|
|
95
|
-
* Opts this column into `RecordPanel`/`RecordPage`'s editable-field API
|
|
96
|
-
* (#431) — click-to-edit there (not this table's own type-driven
|
|
97
|
-
* mechanism, which those two components don't use). Ignored by
|
|
98
|
-
* `RecordsTable` itself. A plain `editable` column, with no `editor`,
|
|
99
|
-
* opens a text/number/date field (inferred from `type`, same inference
|
|
100
|
-
* `DataTable`'s own `editable` columns use — #385); `editor` below picks
|
|
101
|
-
* a `select`/`switch` picker instead. Both consumers require `onEdit` to
|
|
102
|
-
* actually be given for a field to open at all.
|
|
103
|
-
*/
|
|
104
|
-
editable?: boolean;
|
|
105
|
-
/** `select`/`switch` render as the field's own live, always-interactive
|
|
106
|
-
* content instead of opening on click — see `DataTableColumn.editor`
|
|
107
|
-
* (#385) for the identical convention and reasoning. `select` reads
|
|
108
|
-
* `editOptions`. */
|
|
109
|
-
editor?: "select" | "switch";
|
|
110
|
-
/** Options for `editor: "select"` — same shape `DataTable`'s own
|
|
111
|
-
* `DataEditableOption` uses. Not `options` (`StatusOption` requires
|
|
112
|
-
* `color`, for this type's own `status` picker) so this stays additive. */
|
|
113
|
-
editOptions?: EditableOption[];
|
|
114
|
-
};
|
|
115
|
-
export type EntityValue = {
|
|
116
|
-
name: string;
|
|
117
|
-
avatar?: string;
|
|
118
|
-
};
|
|
119
|
-
export type Row = {
|
|
120
|
-
id: string;
|
|
121
|
-
} & Record<string, any>;
|
|
122
|
-
export type RecordsTableProps = Omit<React.ComponentPropsWithoutRef<"div">, "children"> & {
|
|
123
|
-
/** Partial override of the chrome strings; see `recordsTableLabels`. */
|
|
124
|
-
labels?: RecordsTableLabelsInput;
|
|
125
|
-
columns?: Column[];
|
|
126
|
-
rows?: Row[];
|
|
127
|
-
/** Controlled selection — omit for self-managed selection state. */
|
|
128
|
-
selectedIds?: string[];
|
|
129
|
-
onSelectionChange?: (ids: string[]) => void;
|
|
130
|
-
/** Show the toolbar's "New" button (hide it when the page provides its own). */
|
|
131
|
-
showNew?: boolean;
|
|
132
|
-
/** Allow adding columns via the trailing "+" header button (default true). */
|
|
133
|
-
allowAddColumn?: boolean;
|
|
134
|
-
/** Called when a row's open (↗) button is pressed — opens a record panel. */
|
|
135
|
-
onOpenRecord?: (row: Row) => void;
|
|
136
|
-
/** Called when a row's entity name is clicked — navigate to its full record page. */
|
|
137
|
-
onOpenRecordPage?: (row: Row) => void;
|
|
138
|
-
/** Tone for `entity`/`reference` avatars: `"brand"` (uniform, today's
|
|
139
|
-
* measured records-grid behaviour — the default) or `"hashed"` (a
|
|
140
|
-
* stable colour per name, matching what `DataTable`'s `avatarTone` offers).
|
|
141
|
-
* Entity avatars only — `TAG_TONES`/tag/status tone logic is untouched. */
|
|
142
|
-
avatarTone?: "brand" | "hashed";
|
|
143
|
-
/**
|
|
144
|
-
* #603: Attio's zero-*records* state (nothing imported yet, no active
|
|
145
|
-
* filter) adds an "Import CSV" / "Connect data source" pair and a
|
|
146
|
-
* "Learn more" card next to the usual "New record" action -- measured
|
|
147
|
-
* on Users/Workspaces, which show nothing else. Omit any of these and
|
|
148
|
-
* that piece is left out; omit the whole prop and the empty state is
|
|
149
|
-
* unchanged (just "New record"), since this hasn't been confirmed for
|
|
150
|
-
* every object type.
|
|
151
|
-
*/
|
|
152
|
-
emptyStateExtra?: {
|
|
153
|
-
onImportCsv?: () => void;
|
|
154
|
-
onConnectDataSource?: () => void;
|
|
155
|
-
learnMore?: EmptyStateLearnMore;
|
|
156
|
-
};
|
|
157
|
-
className?: string;
|
|
158
|
-
};
|
|
159
|
-
export declare function tagTone(t: string): string;
|
|
160
|
-
type Agg = "none" | "count" | "filled" | "sum" | "avg" | "min" | "max";
|
|
161
|
-
/**
|
|
162
|
-
* Every chrome string RecordsTable renders. Supplied as a PARTIAL map, so
|
|
163
|
-
* translating one menu item does not mean restating the other fifty; anything
|
|
164
|
-
* omitted keeps its English default from `recordsTableLabels`.
|
|
165
|
-
*
|
|
166
|
-
* The interpolated ones are formatters rather than templates because word
|
|
167
|
-
* order does not survive translation — "Sorted by Name +2" has no stable
|
|
168
|
-
* arrangement of its parts across languages (the same reason TableToolbar's
|
|
169
|
-
* triggers take formatters, #77).
|
|
170
|
-
*/
|
|
171
|
-
export type RecordsTableLabels = {
|
|
172
|
-
selectAll: string;
|
|
173
|
-
sort: string;
|
|
174
|
-
sortField: string;
|
|
175
|
-
sortDirection: string;
|
|
176
|
-
removeSort: string;
|
|
177
|
-
reorderSort: string;
|
|
178
|
-
addSort: string;
|
|
179
|
-
ascending: string;
|
|
180
|
-
descending: string;
|
|
181
|
-
noSorts: string;
|
|
182
|
-
learnSorting: string;
|
|
183
|
-
/**
|
|
184
|
-
* Where the sort popover's "Learn about sorting" row links to. Unset by default:
|
|
185
|
-
* the row renders as plain text, since a component library has no help site of its
|
|
186
|
-
* own to point at. Pass your own docs URL to make it a link.
|
|
187
|
-
*/
|
|
188
|
-
learnSortingHref?: string;
|
|
189
|
-
filter: string;
|
|
190
|
-
addFilter: string;
|
|
191
|
-
filterByField: string;
|
|
192
|
-
filterByPlaceholder: string;
|
|
193
|
-
filterValuePlaceholder: string;
|
|
194
|
-
selectCondition: string;
|
|
195
|
-
clearFilter: string;
|
|
196
|
-
addColumn: string;
|
|
197
|
-
columnLabel: string;
|
|
198
|
-
editColumnLabel: string;
|
|
199
|
-
hideFromView: string;
|
|
200
|
-
moveLeft: string;
|
|
201
|
-
moveRight: string;
|
|
202
|
-
sortAscending: string;
|
|
203
|
-
sortDescending: string;
|
|
204
|
-
newRecord: string;
|
|
205
|
-
createRecord: string;
|
|
206
|
-
createMore: string;
|
|
207
|
-
newButton: string;
|
|
208
|
-
more: string;
|
|
209
|
-
moreActions: string;
|
|
210
|
-
recordActions: string;
|
|
211
|
-
copy: string;
|
|
212
|
-
duplicate: string;
|
|
213
|
-
addToList: string;
|
|
214
|
-
inAList: string;
|
|
215
|
-
/** Placeholder in the record search field. */
|
|
216
|
-
searchRecordsPlaceholder: string;
|
|
217
|
-
/** Placeholder in a select cell's option search. */
|
|
218
|
-
searchOptionsPlaceholder: string;
|
|
219
|
-
/** Prefix on the bulk bar's selected count. */
|
|
220
|
-
selectedCount: string;
|
|
221
|
-
/**
|
|
222
|
-
* Announced when the selection changes. A formatter, not a string: the
|
|
223
|
-
* count moves within the sentence between languages. Return "" to say
|
|
224
|
-
* nothing. The bulk bar cannot carry this itself — the consumer mounts it
|
|
225
|
-
* when the first row is picked, so its live region would be created by the
|
|
226
|
-
* very change it should announce (#234).
|
|
227
|
-
*/
|
|
228
|
-
selectionAnnouncement: (count: number) => string;
|
|
229
|
-
delete: string;
|
|
230
|
-
sendEmail: string;
|
|
231
|
-
runWorkflow: string;
|
|
232
|
-
calculate: string;
|
|
233
|
-
emptyPlaceholder: string;
|
|
234
|
-
setRecordPlaceholder: string;
|
|
235
|
-
noRecords: string;
|
|
236
|
-
untitled: string;
|
|
237
|
-
/** #603: the zero-records state's optional extra CTAs. */
|
|
238
|
-
importCsv: string;
|
|
239
|
-
connectDataSource: string;
|
|
240
|
-
/** Aggregation names, keyed by the aggregation. */
|
|
241
|
-
agg: Record<Agg, string>;
|
|
242
|
-
/** Filter operator names, keyed by the operator. */
|
|
243
|
-
op: Record<FilterOp, string>;
|
|
244
|
-
/** Title of the create dialog, given the entity column's label. */
|
|
245
|
-
newRecordTitle: (entity: string) => string;
|
|
246
|
-
/** Placeholder for a create-dialog field, given the field's label. */
|
|
247
|
-
setFieldPlaceholder: (field: string) => string;
|
|
248
|
-
/** Label for a newly added column, given how many columns exist. */
|
|
249
|
-
newColumnLabel: (index: number) => string;
|
|
250
|
-
/** The sort trigger, given the first sorted column and how many more. */
|
|
251
|
-
sortedBy: (first: string, extra: number) => string;
|
|
252
|
-
/** The filter trigger, given how many filters are active. */
|
|
253
|
-
filterCount: (active: number) => string;
|
|
254
|
-
/** The row count under the table. */
|
|
255
|
-
recordCount: (n: number) => string;
|
|
256
|
-
/** Heading above a filter chip's condition editor. */
|
|
257
|
-
conditionTitle: (field: string) => string;
|
|
258
|
-
};
|
|
259
|
-
export declare const recordsTableLabels: RecordsTableLabels;
|
|
260
|
-
/** Partial override of any chrome string; the two keyed maps nest. */
|
|
261
|
-
export type RecordsTableLabelsInput = Partial<Omit<RecordsTableLabels, "agg" | "op">> & {
|
|
262
|
-
agg?: Partial<Record<Agg, string>>;
|
|
263
|
-
op?: Partial<Record<FilterOp, string>>;
|
|
264
|
-
};
|
|
265
|
-
type FilterOp = "contains" | "doesnotcontain" | "startswith" | "endswith" | "is" | "isnot" | "empty" | "notempty";
|
|
266
|
-
/**
|
|
267
|
-
* A date-only cell is a CALENDAR DATE, not an instant. ECMA-262 parses the
|
|
268
|
-
* date-only ISO forms — `1998`, `1998-09`, `1998-09-04` — as UTC midnight, and
|
|
269
|
-
* the field then renders that instant in the reader's own timezone. A
|
|
270
|
-
* `founded: "1998"` field therefore read **Dec 31, 1997** for every reader west
|
|
271
|
-
* of UTC, at every hour of every day, and a date picked east of UTC
|
|
272
|
-
* round-tripped back a day short through `toISOString()` (#220).
|
|
273
|
-
*
|
|
274
|
-
* A string that carries a time is left alone: that one really is an instant,
|
|
275
|
-
* and shifting it would move the moment it names.
|
|
276
|
-
*/
|
|
277
|
-
import { formatCellDate, parseCellDate } from "../../core";
|
|
278
|
-
export { formatCellDate, parseCellDate };
|
|
279
|
-
/**
|
|
280
|
-
* A measured-style record grid — fully featured. Toolbar (search / sort status /
|
|
281
|
-
* count / New), sticky checkbox + entity columns, 36px rows, typed cells,
|
|
282
|
-
* click-to-sort headers, column resize by dragging a header edge, inline cell
|
|
283
|
-
* editing (double-click a text/number/url/date cell), add-row and add-column,
|
|
284
|
-
* and a floating bulk-action bar (delete / deselect) when rows are selected.
|
|
285
|
-
* Selection can be controlled via `selectedIds`/`onSelectionChange`.
|
|
286
|
-
*/
|
|
287
|
-
export declare function RecordsTable({ labels, columns: columnsProp, rows: rowsProp, selectedIds, onSelectionChange, showNew, allowAddColumn, onOpenRecord, onOpenRecordPage, avatarTone, emptyStateExtra, className, ...rest }: RecordsTableProps): React.JSX.Element;
|
|
288
|
-
export declare const defaultColumns: Column[];
|
|
289
|
-
export declare const defaultRows: Row[];
|