@crisp-ui-kit/crisp 0.9.0 → 0.10.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/appshell.css +2 -0
- package/dist/breadcrumb.css +2 -0
- package/dist/cjs/components/breadcrumb/breadcrumb.js +1 -1
- package/dist/cjs/components/breadcrumb/breadcrumb.recipe.js +3 -1
- package/dist/cjs/components/slider/index.js +18 -0
- package/dist/cjs/components/slider/slider.js +22 -0
- package/dist/cjs/components/slider/slider.recipe.js +70 -0
- package/dist/cjs/core/index.js +15 -0
- package/dist/cjs/core/rtl.js +17 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/product/appshell/appshell.js +1 -1
- package/dist/cjs/product/appshell/appshell.recipe.js +2 -0
- package/dist/cjs/product/recordstable/recordstable.js +2 -2
- package/dist/cjs/product/recordstable/recordstable.recipe.js +2 -0
- package/dist/cjs/product/settingsshell/settingsshell.js +1 -1
- package/dist/cjs/product/settingsshell/settingsshell.recipe.js +3 -1
- package/dist/esm/components/breadcrumb/breadcrumb.js +1 -1
- package/dist/esm/components/breadcrumb/breadcrumb.recipe.js +4 -2
- package/dist/esm/components/slider/index.js +2 -0
- package/dist/esm/components/slider/slider.js +19 -0
- package/dist/esm/components/slider/slider.recipe.js +67 -0
- package/dist/esm/core/index.js +1 -0
- package/dist/esm/core/rtl.js +14 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/product/appshell/appshell.js +1 -1
- package/dist/esm/product/appshell/appshell.recipe.js +3 -1
- package/dist/esm/product/recordstable/recordstable.js +2 -2
- package/dist/esm/product/recordstable/recordstable.recipe.js +3 -1
- package/dist/esm/product/settingsshell/settingsshell.js +1 -1
- package/dist/esm/product/settingsshell/settingsshell.recipe.js +4 -2
- package/dist/recordstable.css +2 -0
- package/dist/settingsshell.css +2 -0
- package/dist/slider.css +50 -0
- package/dist/slider.d.ts +7 -0
- package/dist/styles.css +59 -0
- package/dist/types/components/slider/index.d.ts +2 -0
- package/dist/types/components/slider/slider.d.ts +8 -0
- package/dist/types/components/slider/slider.recipe.d.ts +5 -0
- package/dist/types/core/index.d.ts +1 -0
- package/dist/types/core/rtl.d.ts +14 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +7 -1
package/dist/appshell.css
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
& .appshell-expand { position: absolute; top: var(--space-2); inset-inline-start: var(--space-2); z-index: 6; display: inline-flex; align-items: center; justify-content: center; width: var(--size-row); height: var(--size-row); padding: 0; border: none; border-radius: var(--radius-md); box-shadow: inset 0 0 0 1px var(--border-subtle); background: var(--bg-surface); color: var(--fg-muted); font-family: inherit; cursor: pointer; transition: background-color .12s; }
|
|
11
11
|
& .appshell-expand:hover { background: var(--bg-raised); color: var(--fg-primary); }
|
|
12
12
|
|
|
13
|
+
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
14
|
+
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
@media (prefers-reduced-motion: reduce) {
|
package/dist/breadcrumb.css
CHANGED
|
@@ -6,4 +6,6 @@
|
|
|
6
6
|
& button.breadcrumb-item { border: none; background: none; font: inherit; cursor: pointer; }
|
|
7
7
|
& .breadcrumb-item[aria-current] { color: var(--fg-primary); font-weight: var(--weight-medium); }
|
|
8
8
|
& .breadcrumb-sep { flex-shrink: 0; color: color-mix(in srgb, var(--fg-primary) 28%, transparent); }
|
|
9
|
+
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
10
|
+
|
|
9
11
|
}
|
|
@@ -43,7 +43,7 @@ const breadcrumb_recipe_1 = require("./breadcrumb.recipe");
|
|
|
43
43
|
* marked `aria-current="page"`; earlier items render as links or buttons.
|
|
44
44
|
*/
|
|
45
45
|
function Breadcrumb({ items, separator, "aria-label": ariaLabel = "Breadcrumb", className, ...rest }) {
|
|
46
|
-
const sep = separator ?? ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" }));
|
|
46
|
+
const sep = separator ?? ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { "data-rtl-flip": "", size: 14, strokeWidth: 1.75, "aria-hidden": "true" }));
|
|
47
47
|
return ((0, jsx_runtime_1.jsx)("nav", { "aria-label": ariaLabel, className: (0, breadcrumb_recipe_1.breadcrumbRecipe)({ className }), ...rest, children: items.map((item, i) => {
|
|
48
48
|
const last = i === items.length - 1;
|
|
49
49
|
const content = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [item.icon, item.label] }));
|
|
@@ -12,7 +12,9 @@ const config = (0, core_1.defineRecipe)({
|
|
|
12
12
|
& a.breadcrumb-item:hover, & button.breadcrumb-item:hover { color: ${tokens_1.contract.fgPrimary}; background: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 5%, transparent); }
|
|
13
13
|
& button.breadcrumb-item { border: none; background: none; font: inherit; cursor: pointer; }
|
|
14
14
|
& .breadcrumb-item[aria-current] { color: ${tokens_1.contract.fgPrimary}; font-weight: ${tokens_1.contract.weight.medium}; }
|
|
15
|
-
& .breadcrumb-sep { flex-shrink: 0; color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 28%, transparent); }
|
|
15
|
+
& .breadcrumb-sep { flex-shrink: 0; color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 28%, transparent); }
|
|
16
|
+
${core_1.rtlFlipCss}
|
|
17
|
+
`,
|
|
16
18
|
variants: {},
|
|
17
19
|
defaultVariants: {},
|
|
18
20
|
compoundVariants: [],
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./slider"), exports);
|
|
18
|
+
__exportStar(require("./slider.recipe"), exports);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.Slider = Slider;
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const react_slider_1 = require("@seed-design/react-slider");
|
|
7
|
+
const slider_recipe_1 = require("./slider.recipe");
|
|
8
|
+
/** Reads the thumb count from the engine rather than re-deriving it from props. */
|
|
9
|
+
function Thumbs() {
|
|
10
|
+
const { values } = (0, react_slider_1.useSliderContext)();
|
|
11
|
+
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: values.map((_, i) => ((0, jsx_runtime_1.jsx)(react_slider_1.SliderThumb
|
|
12
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: thumbs are positional — the index IS the identity the engine addresses them by
|
|
13
|
+
, { thumbIndex: i, className: "slider-thumb" }, i))) }));
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A range input, driven by seed-design's headless engine so the keyboard model,
|
|
17
|
+
* the pointer maths and multi-thumb constraints are theirs by construction.
|
|
18
|
+
* Pass one value for a simple slider, two for a range.
|
|
19
|
+
*/
|
|
20
|
+
function Slider({ className, ...props }) {
|
|
21
|
+
return ((0, jsx_runtime_1.jsx)(react_slider_1.SliderRoot, { ...props, className: (0, slider_recipe_1.sliderRecipe)({ className }), children: (0, jsx_runtime_1.jsxs)("span", { className: "slider-control", children: [(0, jsx_runtime_1.jsx)("span", { className: "slider-track", children: (0, jsx_runtime_1.jsx)(react_slider_1.SliderRange, { className: "slider-range" }) }), (0, jsx_runtime_1.jsx)(Thumbs, {})] }) }));
|
|
22
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sliderRecipe = void 0;
|
|
4
|
+
const core_1 = require("../../core");
|
|
5
|
+
const tokens_1 = require("../../tokens");
|
|
6
|
+
// seed-design's slider, shape for shape, in crisp's colours.
|
|
7
|
+
//
|
|
8
|
+
// Attio ships no slider anywhere — Records, Reports, Settings and the record
|
|
9
|
+
// pages contain no `input[type=range]` or `[role=slider]` — so there is nothing
|
|
10
|
+
// of Attio's to measure. The GEOMETRY is therefore seed's own, read from
|
|
11
|
+
// `@seed-design/css/recipes/slider.css`: a 26px control row, a 4px track on
|
|
12
|
+
// `radius.full`, a 20px thumb whose visible disc is an `::after` that scales to
|
|
13
|
+
// 1.2 while dragging, and a 2px focus ring offset 2px.
|
|
14
|
+
//
|
|
15
|
+
// Only the COLOUR roles are re-pointed at crisp's tokens:
|
|
16
|
+
// seed gray-400 track -> bgNeutralWeak (crisp's weak neutral fill)
|
|
17
|
+
// seed fg-neutral range -> bgBrandSolid (crisp fills with brand, as Progress does)
|
|
18
|
+
// seed bg-neutral-inverted -> #fff + elevation.field (crisp's control disc, as Switch does)
|
|
19
|
+
//
|
|
20
|
+
// Position comes from the engine's own `--range-start`/`--range-end` and
|
|
21
|
+
// `--thumb-position`/`--thumb-offset`, switched on the `data-dir` it stamps —
|
|
22
|
+
// the same mechanism seed uses, rather than CSS direction inheritance.
|
|
23
|
+
const config = (0, core_1.defineRecipe)({
|
|
24
|
+
name: "slider",
|
|
25
|
+
base: `
|
|
26
|
+
display: flex; flex-direction: column; align-items: stretch;
|
|
27
|
+
width: 100%; min-width: 0; gap: ${tokens_1.contract.space["0.5"]};
|
|
28
|
+
font-family: ${tokens_1.contract.font.sans}; user-select: none; touch-action: none;
|
|
29
|
+
|
|
30
|
+
& .slider-control { position: relative; height: 26px; display: flex; align-items: center; }
|
|
31
|
+
|
|
32
|
+
& .slider-track {
|
|
33
|
+
position: relative; flex-grow: 1; height: ${tokens_1.contract.space["1"]};
|
|
34
|
+
border-radius: ${tokens_1.contract.radius.full}; background: ${tokens_1.contract.bgNeutralWeak};
|
|
35
|
+
overflow: hidden;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
& .slider-range { position: absolute; height: 100%; background: ${tokens_1.contract.bgBrandSolid}; }
|
|
39
|
+
& .slider-range[data-dir="ltr"] { left: var(--range-start); right: var(--range-end); }
|
|
40
|
+
& .slider-range[data-dir="rtl"] { right: var(--range-start); left: var(--range-end); }
|
|
41
|
+
|
|
42
|
+
& .slider-thumb {
|
|
43
|
+
position: absolute; top: 50%;
|
|
44
|
+
width: ${tokens_1.contract.space["5"]}; height: ${tokens_1.contract.space["5"]};
|
|
45
|
+
transform: translate(-50%, -50%);
|
|
46
|
+
border: none; background: none; padding: 0;
|
|
47
|
+
}
|
|
48
|
+
& .slider-thumb[data-dir="ltr"] { left: calc(var(--thumb-position) * 1% + var(--thumb-offset)); }
|
|
49
|
+
& .slider-thumb[data-dir="rtl"] { right: calc(var(--thumb-position) * 1% + var(--thumb-offset)); }
|
|
50
|
+
& .slider-thumb::after {
|
|
51
|
+
content: ""; position: absolute; inset: 0;
|
|
52
|
+
border-radius: ${tokens_1.contract.radius.full}; background: #fff; box-shadow: ${tokens_1.elevation.field};
|
|
53
|
+
outline: 2px solid transparent; outline-offset: 2px;
|
|
54
|
+
transition: transform .2s ease, outline-color .2s ease;
|
|
55
|
+
cursor: grab;
|
|
56
|
+
}
|
|
57
|
+
& .slider-thumb[data-thumb-dragging]::after { transform: scale(1.2); cursor: grabbing; }
|
|
58
|
+
& .slider-thumb:focus { outline: none; }
|
|
59
|
+
& .slider-thumb:focus-visible::after { outline-color: ${tokens_1.contract.strokeFocusRing}; }
|
|
60
|
+
|
|
61
|
+
&[data-disabled] { cursor: not-allowed; }
|
|
62
|
+
&[data-disabled] .slider-range { background: ${tokens_1.contract.fgDisabled}; }
|
|
63
|
+
&[data-disabled] .slider-thumb::after { cursor: not-allowed; }
|
|
64
|
+
`,
|
|
65
|
+
variants: {},
|
|
66
|
+
defaultVariants: {},
|
|
67
|
+
compoundVariants: [],
|
|
68
|
+
});
|
|
69
|
+
exports.sliderRecipe = Object.assign((0, core_1.resolveRecipe)(config), { config });
|
|
70
|
+
exports.default = config;
|
package/dist/cjs/core/index.js
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
17
|
exports.resolveRecipe = exports.Primitive = exports.defineRecipe = exports.cx = void 0;
|
|
4
18
|
var cx_1 = require("./cx");
|
|
@@ -9,3 +23,4 @@ var primitive_1 = require("./primitive");
|
|
|
9
23
|
Object.defineProperty(exports, "Primitive", { enumerable: true, get: function () { return primitive_1.Primitive; } });
|
|
10
24
|
var resolve_1 = require("./resolve");
|
|
11
25
|
Object.defineProperty(exports, "resolveRecipe", { enumerable: true, get: function () { return resolve_1.resolveRecipe; } });
|
|
26
|
+
__exportStar(require("./rtl"), exports);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rtlFlipCss = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Mirroring for direction-bearing icons.
|
|
6
|
+
*
|
|
7
|
+
* A chevron or arrow that means "back", "next", "toward the start" or "open"
|
|
8
|
+
* points the wrong way under RTL, and unlike spacing or alignment it cannot be
|
|
9
|
+
* fixed with a logical property: these are `lucide-react` nodes, static SVG
|
|
10
|
+
* paths with no direction of their own.
|
|
11
|
+
*
|
|
12
|
+
* Mark the icons that carry a direction with `data-rtl-flip` and include this
|
|
13
|
+
* snippet in the recipe. Icons whose meaning is NOT directional — a downward
|
|
14
|
+
* disclosure chevron, a search glass, a check — must be left unmarked: flipping
|
|
15
|
+
* them is a regression, not a fix.
|
|
16
|
+
*/
|
|
17
|
+
exports.rtlFlipCss = `[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }`;
|
package/dist/cjs/index.js
CHANGED
|
@@ -53,6 +53,7 @@ __exportStar(require("./components/resizablepanel"), exports);
|
|
|
53
53
|
__exportStar(require("./components/segmented"), exports);
|
|
54
54
|
__exportStar(require("./components/select"), exports);
|
|
55
55
|
__exportStar(require("./components/skeleton"), exports);
|
|
56
|
+
__exportStar(require("./components/slider"), exports);
|
|
56
57
|
__exportStar(require("./components/spinner"), exports);
|
|
57
58
|
__exportStar(require("./components/stagebar"), exports);
|
|
58
59
|
__exportStar(require("./components/statcard"), exports);
|
|
@@ -99,6 +99,6 @@ function AppShell({ sidebar, children, width: widthProp, defaultWidth = 275, onW
|
|
|
99
99
|
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, appshell_recipe_1.appshellRecipe)({ className }), ...rest, children: [(0, jsx_runtime_1.jsxs)("div", { className: "appshell-side", "data-collapsed": collapsed ? "" : undefined, style: {
|
|
100
100
|
width: collapsed ? 0 : width,
|
|
101
101
|
transition: dragging ? "none" : "width .14s ease",
|
|
102
|
-
}, children: [(0, jsx_runtime_1.jsx)("div", { className: "appshell-side-inner", style: { width }, children: sidebar(toggleCollapse) }), !collapsed && ((0, jsx_runtime_1.jsx)("div", { className: "appshell-resize", "data-dragging": dragging ? "" : undefined, "aria-hidden": "true", onPointerDown: startResize }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "appshell-main", children: [collapsed && ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "appshell-expand", "aria-label": expandLabel, onClick: () => setCollapsed(false), children: (0, jsx_runtime_1.jsx)(lucide_react_1.PanelLeft, { size: 15, strokeWidth: 1.75 }) })), children] })] }));
|
|
102
|
+
}, children: [(0, jsx_runtime_1.jsx)("div", { className: "appshell-side-inner", style: { width }, children: sidebar(toggleCollapse) }), !collapsed && ((0, jsx_runtime_1.jsx)("div", { className: "appshell-resize", "data-dragging": dragging ? "" : undefined, "aria-hidden": "true", onPointerDown: startResize }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "appshell-main", children: [collapsed && ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "appshell-expand", "aria-label": expandLabel, onClick: () => setCollapsed(false), children: (0, jsx_runtime_1.jsx)(lucide_react_1.PanelLeft, { "data-rtl-flip": "", size: 15, strokeWidth: 1.75 }) })), children] })] }));
|
|
103
103
|
}
|
|
104
104
|
AppShell.displayName = "AppShell";
|
|
@@ -18,6 +18,8 @@ const config = (0, core_1.defineRecipe)({
|
|
|
18
18
|
& .appshell-main { position: relative; flex: 1; min-width: 0; display: flex; flex-direction: column; overflow: hidden; }
|
|
19
19
|
& .appshell-expand { position: absolute; top: ${tokens_1.contract.space["2"]}; inset-inline-start: ${tokens_1.contract.space["2"]}; z-index: 6; display: inline-flex; align-items: center; justify-content: center; width: ${tokens_1.contract.size.row}; height: ${tokens_1.contract.size.row}; padding: 0; border: none; border-radius: ${tokens_1.contract.radius.md}; box-shadow: inset 0 0 0 1px ${tokens_1.contract.borderSubtle}; background: ${tokens_1.contract.bgSurface}; color: ${tokens_1.contract.fgMuted}; font-family: inherit; cursor: pointer; transition: background-color .12s; }
|
|
20
20
|
& .appshell-expand:hover { background: ${tokens_1.contract.bgRaised}; color: ${tokens_1.contract.fgPrimary}; }
|
|
21
|
+
|
|
22
|
+
${core_1.rtlFlipCss}
|
|
21
23
|
`,
|
|
22
24
|
variants: {},
|
|
23
25
|
defaultVariants: {},
|
|
@@ -984,7 +984,7 @@ function RecordsTable({ labels, columns: columnsProp = exports.defaultColumns, r
|
|
|
984
984
|
}
|
|
985
985
|
: undefined, onDragEnd: () => setDragCol(null), onClick: (e) => openColumnMenu(col.key, e.currentTarget), children: [Icon ? (0, jsx_runtime_1.jsx)(Icon, { size: 14, strokeWidth: 1.75 }) : null, (0, jsx_runtime_1.jsx)("span", { className: "recordstable-th-label", children: col.label }), (0, jsx_runtime_1.jsx)("span", { className: "recordstable-sort", children: (0, jsx_runtime_1.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("path", { d: "m4 6 4 4 4-4" }) }) })] })), openMenu === `col:${col.key}` &&
|
|
986
986
|
rootRef.current &&
|
|
987
|
-
(0, react_dom_1.createPortal)((0, jsx_runtime_1.jsxs)("div", { ref: menuRef, className: "recordstable-menu recordstable-menu--fixed recordstable-menu--hdr", role: "menu", "aria-label": `${col.label} column`, style: menuPos ?? undefined, onKeyDown: onMenuKeyDown, children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => sortBy(col.key, "asc"), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowUp, { size: 15, strokeWidth: 1.75 }), t.sortAscending] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => sortBy(col.key, "desc"), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowDown, { size: 15, strokeWidth: 1.75 }), t.sortDescending] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, disabled: i <= 1, onClick: () => moveColumn(col.key, -1), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowLeft, { size: 15, strokeWidth: 1.75 }), t.moveLeft] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, disabled: i === 0 || i >= cols.length - 1, onClick: () => moveColumn(col.key, 1), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowRight, { size: 15, strokeWidth: 1.75 }), t.moveRight] }), (0, jsx_runtime_1.jsx)("div", { className: "recordstable-menu-sep" }), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => {
|
|
987
|
+
(0, react_dom_1.createPortal)((0, jsx_runtime_1.jsxs)("div", { ref: menuRef, className: "recordstable-menu recordstable-menu--fixed recordstable-menu--hdr", role: "menu", "aria-label": `${col.label} column`, style: menuPos ?? undefined, onKeyDown: onMenuKeyDown, children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => sortBy(col.key, "asc"), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowUp, { size: 15, strokeWidth: 1.75 }), t.sortAscending] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => sortBy(col.key, "desc"), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowDown, { size: 15, strokeWidth: 1.75 }), t.sortDescending] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, disabled: i <= 1, onClick: () => moveColumn(col.key, -1), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowLeft, { "data-rtl-flip": "", size: 15, strokeWidth: 1.75 }), t.moveLeft] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, disabled: i === 0 || i >= cols.length - 1, onClick: () => moveColumn(col.key, 1), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ArrowRight, { "data-rtl-flip": "", size: 15, strokeWidth: 1.75 }), t.moveRight] }), (0, jsx_runtime_1.jsx)("div", { className: "recordstable-menu-sep" }), (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => {
|
|
988
988
|
setRenamingCol(col.key);
|
|
989
989
|
setOpenMenu(null);
|
|
990
990
|
}, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Pencil, { size: 15, strokeWidth: 1.75 }), t.editColumnLabel] }), cols.length > 1 && ((0, jsx_runtime_1.jsxs)("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => hideColumn(col.key), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.EyeOff, { size: 15, strokeWidth: 1.75 }), t.hideFromView] }))] }), rootRef.current), (0, jsx_runtime_1.jsx)("span", { className: "recordstable-resize", "aria-hidden": "true", onPointerDown: (e) => {
|
|
@@ -1025,7 +1025,7 @@ function RecordsTable({ labels, columns: columnsProp = exports.defaultColumns, r
|
|
|
1025
1025
|
: undefined, avatarTone: avatarTone })), i === 0 && onOpenRecord && !isEditing && ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "recordstable-open", "aria-label": `Open ${cellText(col, row)}`, onClick: (e) => {
|
|
1026
1026
|
e.stopPropagation();
|
|
1027
1027
|
onOpenRecord(row);
|
|
1028
|
-
}, children: (0, jsx_runtime_1.jsx)(lucide_react_1.ArrowUpRight, { size: 15, strokeWidth: 1.75 }) }))] }, col.key));
|
|
1028
|
+
}, children: (0, jsx_runtime_1.jsx)(lucide_react_1.ArrowUpRight, { "data-rtl-flip": "", size: 15, strokeWidth: 1.75 }) }))] }, col.key));
|
|
1029
1029
|
}), (0, jsx_runtime_1.jsx)("td", { className: "recordstable-td recordstable-addcol" })] }, row.id))) }), (0, jsx_runtime_1.jsx)("tfoot", { children: (0, jsx_runtime_1.jsxs)("tr", { children: [(0, jsx_runtime_1.jsx)("td", { className: "recordstable-sum recordstable-col-check" }), cols.map((col, i) => {
|
|
1030
1030
|
const a = agg[col.key] ?? "none";
|
|
1031
1031
|
const res = summarize(col, a, visibleRows);
|
|
@@ -145,6 +145,8 @@ ${(0, tabletoolbar_chrome_1.toolbarChromeBody)("recordstable")}
|
|
|
145
145
|
& .recordstable-bulk-sep { width: 1px; height: 20px; margin: 0 ${tokens_1.contract.space["0.5"]}; background: ${tokens_1.contract.borderSubtle}; }
|
|
146
146
|
& .recordstable-bulk-close { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: none; border-radius: ${tokens_1.contract.radius.md}; background: transparent; color: ${tokens_1.contract.fgMuted}; cursor: pointer; }
|
|
147
147
|
& .recordstable-bulk-close:hover { background: ${tokens_1.contract.bgRaised}; color: ${tokens_1.contract.fgPrimary}; }
|
|
148
|
+
|
|
149
|
+
${core_1.rtlFlipCss}
|
|
148
150
|
`,
|
|
149
151
|
variants: {},
|
|
150
152
|
defaultVariants: {},
|
|
@@ -54,6 +54,6 @@ function SettingsShell({ title = "Settings", onBack, groups, activeItem, onSelec
|
|
|
54
54
|
}))
|
|
55
55
|
.filter((g) => g.items.length > 0)
|
|
56
56
|
: groups;
|
|
57
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, settingsshell_recipe_1.settingsshellRecipe)({ className }), ...rest, children: [(0, jsx_runtime_1.jsxs)("nav", { className: "settingsshell-nav", "aria-label": navLabel, children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: "settingsshell-back", onClick: onBack, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { size: 16, strokeWidth: 2 }), title] }), searchable && ((0, jsx_runtime_1.jsxs)("div", { className: "settingsshell-search", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Search, { size: 15, strokeWidth: 1.75 }), (0, jsx_runtime_1.jsx)("input", { type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, value: query, onChange: (e) => setQuery(e.target.value) })] })), (0, jsx_runtime_1.jsx)("div", { className: "settingsshell-groups", children: filtered.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "settingsshell-empty", children: emptyLabel })) : (filtered.map((g, gi) => ((0, jsx_runtime_1.jsxs)("div", { className: "settingsshell-group", children: [g.label != null && ((0, jsx_runtime_1.jsx)("div", { className: "settingsshell-group-label", children: g.label })), g.items.map((it) => ((0, jsx_runtime_1.jsxs)("button", { type: "button", className: "settingsshell-item", "aria-current": it.id === activeItem ? "page" : undefined, "data-active": it.id === activeItem ? "" : undefined, onClick: () => onSelect(it.id), children: [it.icon, (0, jsx_runtime_1.jsx)("span", { className: "settingsshell-item-label", children: it.label })] }, it.id)))] }, gi)))) })] }), (0, jsx_runtime_1.jsx)("div", { className: "settingsshell-content", children: children })] }));
|
|
57
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, settingsshell_recipe_1.settingsshellRecipe)({ className }), ...rest, children: [(0, jsx_runtime_1.jsxs)("nav", { className: "settingsshell-nav", "aria-label": navLabel, children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", className: "settingsshell-back", onClick: onBack, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { "data-rtl-flip": "", size: 16, strokeWidth: 2 }), title] }), searchable && ((0, jsx_runtime_1.jsxs)("div", { className: "settingsshell-search", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Search, { size: 15, strokeWidth: 1.75 }), (0, jsx_runtime_1.jsx)("input", { type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, value: query, onChange: (e) => setQuery(e.target.value) })] })), (0, jsx_runtime_1.jsx)("div", { className: "settingsshell-groups", children: filtered.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "settingsshell-empty", children: emptyLabel })) : (filtered.map((g, gi) => ((0, jsx_runtime_1.jsxs)("div", { className: "settingsshell-group", children: [g.label != null && ((0, jsx_runtime_1.jsx)("div", { className: "settingsshell-group-label", children: g.label })), g.items.map((it) => ((0, jsx_runtime_1.jsxs)("button", { type: "button", className: "settingsshell-item", "aria-current": it.id === activeItem ? "page" : undefined, "data-active": it.id === activeItem ? "" : undefined, onClick: () => onSelect(it.id), children: [it.icon, (0, jsx_runtime_1.jsx)("span", { className: "settingsshell-item-label", children: it.label })] }, it.id)))] }, gi)))) })] }), (0, jsx_runtime_1.jsx)("div", { className: "settingsshell-content", children: children })] }));
|
|
58
58
|
}
|
|
59
59
|
SettingsShell.displayName = "SettingsShell";
|
|
@@ -37,7 +37,9 @@ const config = (0, core_1.defineRecipe)({
|
|
|
37
37
|
& .settingsshell-item[data-active] svg { color: ${tokens_1.contract.fgPrimary}; }
|
|
38
38
|
& .settingsshell-empty { padding: ${tokens_1.contract.space["3"]} ${tokens_1.contract.space["2"]}; font-size: ${tokens_1.contract.text.md}; color: ${tokens_1.contract.fgMuted}; }
|
|
39
39
|
|
|
40
|
-
& .settingsshell-content { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; padding: ${tokens_1.contract.space["6"]} ${tokens_1.contract.space["8"]}; }
|
|
40
|
+
& .settingsshell-content { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; padding: ${tokens_1.contract.space["6"]} ${tokens_1.contract.space["8"]}; }
|
|
41
|
+
${core_1.rtlFlipCss}
|
|
42
|
+
`,
|
|
41
43
|
variants: {},
|
|
42
44
|
defaultVariants: {},
|
|
43
45
|
compoundVariants: [],
|
|
@@ -7,7 +7,7 @@ import { breadcrumbRecipe } from "./breadcrumb.recipe.js";
|
|
|
7
7
|
* marked `aria-current="page"`; earlier items render as links or buttons.
|
|
8
8
|
*/
|
|
9
9
|
export function Breadcrumb({ items, separator, "aria-label": ariaLabel = "Breadcrumb", className, ...rest }) {
|
|
10
|
-
const sep = separator ?? (_jsx(ChevronRight, { size: 14, strokeWidth: 1.75, "aria-hidden": "true" }));
|
|
10
|
+
const sep = separator ?? (_jsx(ChevronRight, { "data-rtl-flip": "", size: 14, strokeWidth: 1.75, "aria-hidden": "true" }));
|
|
11
11
|
return (_jsx("nav", { "aria-label": ariaLabel, className: breadcrumbRecipe({ className }), ...rest, children: items.map((item, i) => {
|
|
12
12
|
const last = i === items.length - 1;
|
|
13
13
|
const content = (_jsxs(_Fragment, { children: [item.icon, item.label] }));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineRecipe, resolveRecipe } from "../../core/index.js";
|
|
1
|
+
import { defineRecipe, resolveRecipe, rtlFlipCss } from "../../core/index.js";
|
|
2
2
|
import { contract as c } from "../../tokens/index.js";
|
|
3
3
|
// A breadcrumb trail — Attio's record-page nav ("Companies / Google").
|
|
4
4
|
const config = defineRecipe({
|
|
@@ -9,7 +9,9 @@ const config = defineRecipe({
|
|
|
9
9
|
& a.breadcrumb-item:hover, & button.breadcrumb-item:hover { color: ${c.fgPrimary}; background: color-mix(in srgb, ${c.fgPrimary} 5%, transparent); }
|
|
10
10
|
& button.breadcrumb-item { border: none; background: none; font: inherit; cursor: pointer; }
|
|
11
11
|
& .breadcrumb-item[aria-current] { color: ${c.fgPrimary}; font-weight: ${c.weight.medium}; }
|
|
12
|
-
& .breadcrumb-sep { flex-shrink: 0; color: color-mix(in srgb, ${c.fgPrimary} 28%, transparent); }
|
|
12
|
+
& .breadcrumb-sep { flex-shrink: 0; color: color-mix(in srgb, ${c.fgPrimary} 28%, transparent); }
|
|
13
|
+
${rtlFlipCss}
|
|
14
|
+
`,
|
|
13
15
|
variants: {},
|
|
14
16
|
defaultVariants: {},
|
|
15
17
|
compoundVariants: [],
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { SliderRange, SliderRoot, SliderThumb, useSliderContext, } from "@seed-design/react-slider";
|
|
4
|
+
import { sliderRecipe } from "./slider.recipe.js";
|
|
5
|
+
/** Reads the thumb count from the engine rather than re-deriving it from props. */
|
|
6
|
+
function Thumbs() {
|
|
7
|
+
const { values } = useSliderContext();
|
|
8
|
+
return (_jsx(_Fragment, { children: values.map((_, i) => (_jsx(SliderThumb
|
|
9
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: thumbs are positional — the index IS the identity the engine addresses them by
|
|
10
|
+
, { thumbIndex: i, className: "slider-thumb" }, i))) }));
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A range input, driven by seed-design's headless engine so the keyboard model,
|
|
14
|
+
* the pointer maths and multi-thumb constraints are theirs by construction.
|
|
15
|
+
* Pass one value for a simple slider, two for a range.
|
|
16
|
+
*/
|
|
17
|
+
export function Slider({ className, ...props }) {
|
|
18
|
+
return (_jsx(SliderRoot, { ...props, className: sliderRecipe({ className }), children: _jsxs("span", { className: "slider-control", children: [_jsx("span", { className: "slider-track", children: _jsx(SliderRange, { className: "slider-range" }) }), _jsx(Thumbs, {})] }) }));
|
|
19
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { defineRecipe, resolveRecipe } from "../../core/index.js";
|
|
2
|
+
import { contract as c, elevation as e } from "../../tokens/index.js";
|
|
3
|
+
// seed-design's slider, shape for shape, in crisp's colours.
|
|
4
|
+
//
|
|
5
|
+
// Attio ships no slider anywhere — Records, Reports, Settings and the record
|
|
6
|
+
// pages contain no `input[type=range]` or `[role=slider]` — so there is nothing
|
|
7
|
+
// of Attio's to measure. The GEOMETRY is therefore seed's own, read from
|
|
8
|
+
// `@seed-design/css/recipes/slider.css`: a 26px control row, a 4px track on
|
|
9
|
+
// `radius.full`, a 20px thumb whose visible disc is an `::after` that scales to
|
|
10
|
+
// 1.2 while dragging, and a 2px focus ring offset 2px.
|
|
11
|
+
//
|
|
12
|
+
// Only the COLOUR roles are re-pointed at crisp's tokens:
|
|
13
|
+
// seed gray-400 track -> bgNeutralWeak (crisp's weak neutral fill)
|
|
14
|
+
// seed fg-neutral range -> bgBrandSolid (crisp fills with brand, as Progress does)
|
|
15
|
+
// seed bg-neutral-inverted -> #fff + elevation.field (crisp's control disc, as Switch does)
|
|
16
|
+
//
|
|
17
|
+
// Position comes from the engine's own `--range-start`/`--range-end` and
|
|
18
|
+
// `--thumb-position`/`--thumb-offset`, switched on the `data-dir` it stamps —
|
|
19
|
+
// the same mechanism seed uses, rather than CSS direction inheritance.
|
|
20
|
+
const config = defineRecipe({
|
|
21
|
+
name: "slider",
|
|
22
|
+
base: `
|
|
23
|
+
display: flex; flex-direction: column; align-items: stretch;
|
|
24
|
+
width: 100%; min-width: 0; gap: ${c.space["0.5"]};
|
|
25
|
+
font-family: ${c.font.sans}; user-select: none; touch-action: none;
|
|
26
|
+
|
|
27
|
+
& .slider-control { position: relative; height: 26px; display: flex; align-items: center; }
|
|
28
|
+
|
|
29
|
+
& .slider-track {
|
|
30
|
+
position: relative; flex-grow: 1; height: ${c.space["1"]};
|
|
31
|
+
border-radius: ${c.radius.full}; background: ${c.bgNeutralWeak};
|
|
32
|
+
overflow: hidden;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
& .slider-range { position: absolute; height: 100%; background: ${c.bgBrandSolid}; }
|
|
36
|
+
& .slider-range[data-dir="ltr"] { left: var(--range-start); right: var(--range-end); }
|
|
37
|
+
& .slider-range[data-dir="rtl"] { right: var(--range-start); left: var(--range-end); }
|
|
38
|
+
|
|
39
|
+
& .slider-thumb {
|
|
40
|
+
position: absolute; top: 50%;
|
|
41
|
+
width: ${c.space["5"]}; height: ${c.space["5"]};
|
|
42
|
+
transform: translate(-50%, -50%);
|
|
43
|
+
border: none; background: none; padding: 0;
|
|
44
|
+
}
|
|
45
|
+
& .slider-thumb[data-dir="ltr"] { left: calc(var(--thumb-position) * 1% + var(--thumb-offset)); }
|
|
46
|
+
& .slider-thumb[data-dir="rtl"] { right: calc(var(--thumb-position) * 1% + var(--thumb-offset)); }
|
|
47
|
+
& .slider-thumb::after {
|
|
48
|
+
content: ""; position: absolute; inset: 0;
|
|
49
|
+
border-radius: ${c.radius.full}; background: #fff; box-shadow: ${e.field};
|
|
50
|
+
outline: 2px solid transparent; outline-offset: 2px;
|
|
51
|
+
transition: transform .2s ease, outline-color .2s ease;
|
|
52
|
+
cursor: grab;
|
|
53
|
+
}
|
|
54
|
+
& .slider-thumb[data-thumb-dragging]::after { transform: scale(1.2); cursor: grabbing; }
|
|
55
|
+
& .slider-thumb:focus { outline: none; }
|
|
56
|
+
& .slider-thumb:focus-visible::after { outline-color: ${c.strokeFocusRing}; }
|
|
57
|
+
|
|
58
|
+
&[data-disabled] { cursor: not-allowed; }
|
|
59
|
+
&[data-disabled] .slider-range { background: ${c.fgDisabled}; }
|
|
60
|
+
&[data-disabled] .slider-thumb::after { cursor: not-allowed; }
|
|
61
|
+
`,
|
|
62
|
+
variants: {},
|
|
63
|
+
defaultVariants: {},
|
|
64
|
+
compoundVariants: [],
|
|
65
|
+
});
|
|
66
|
+
export const sliderRecipe = Object.assign(resolveRecipe(config), { config });
|
|
67
|
+
export default config;
|
package/dist/esm/core/index.js
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mirroring for direction-bearing icons.
|
|
3
|
+
*
|
|
4
|
+
* A chevron or arrow that means "back", "next", "toward the start" or "open"
|
|
5
|
+
* points the wrong way under RTL, and unlike spacing or alignment it cannot be
|
|
6
|
+
* fixed with a logical property: these are `lucide-react` nodes, static SVG
|
|
7
|
+
* paths with no direction of their own.
|
|
8
|
+
*
|
|
9
|
+
* Mark the icons that carry a direction with `data-rtl-flip` and include this
|
|
10
|
+
* snippet in the recipe. Icons whose meaning is NOT directional — a downward
|
|
11
|
+
* disclosure chevron, a search glass, a check — must be left unmarked: flipping
|
|
12
|
+
* them is a regression, not a fix.
|
|
13
|
+
*/
|
|
14
|
+
export const rtlFlipCss = `[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }`;
|
package/dist/esm/index.js
CHANGED
|
@@ -37,6 +37,7 @@ export * from "./components/resizablepanel/index.js";
|
|
|
37
37
|
export * from "./components/segmented/index.js";
|
|
38
38
|
export * from "./components/select/index.js";
|
|
39
39
|
export * from "./components/skeleton/index.js";
|
|
40
|
+
export * from "./components/slider/index.js";
|
|
40
41
|
export * from "./components/spinner/index.js";
|
|
41
42
|
export * from "./components/stagebar/index.js";
|
|
42
43
|
export * from "./components/statcard/index.js";
|
|
@@ -63,6 +63,6 @@ export function AppShell({ sidebar, children, width: widthProp, defaultWidth = 2
|
|
|
63
63
|
return (_jsxs("div", { className: appshellRecipe({ className }), ...rest, children: [_jsxs("div", { className: "appshell-side", "data-collapsed": collapsed ? "" : undefined, style: {
|
|
64
64
|
width: collapsed ? 0 : width,
|
|
65
65
|
transition: dragging ? "none" : "width .14s ease",
|
|
66
|
-
}, children: [_jsx("div", { className: "appshell-side-inner", style: { width }, children: sidebar(toggleCollapse) }), !collapsed && (_jsx("div", { className: "appshell-resize", "data-dragging": dragging ? "" : undefined, "aria-hidden": "true", onPointerDown: startResize }))] }), _jsxs("div", { className: "appshell-main", children: [collapsed && (_jsx("button", { type: "button", className: "appshell-expand", "aria-label": expandLabel, onClick: () => setCollapsed(false), children: _jsx(PanelLeft, { size: 15, strokeWidth: 1.75 }) })), children] })] }));
|
|
66
|
+
}, children: [_jsx("div", { className: "appshell-side-inner", style: { width }, children: sidebar(toggleCollapse) }), !collapsed && (_jsx("div", { className: "appshell-resize", "data-dragging": dragging ? "" : undefined, "aria-hidden": "true", onPointerDown: startResize }))] }), _jsxs("div", { className: "appshell-main", children: [collapsed && (_jsx("button", { type: "button", className: "appshell-expand", "aria-label": expandLabel, onClick: () => setCollapsed(false), children: _jsx(PanelLeft, { "data-rtl-flip": "", size: 15, strokeWidth: 1.75 }) })), children] })] }));
|
|
67
67
|
}
|
|
68
68
|
AppShell.displayName = "AppShell";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineRecipe, resolveRecipe } from "../../core/index.js";
|
|
1
|
+
import { defineRecipe, resolveRecipe, rtlFlipCss } from "../../core/index.js";
|
|
2
2
|
import { contract as c } from "../../tokens/index.js";
|
|
3
3
|
// App-shell layout: a collapsible + resizable sidebar pane next to a main pane,
|
|
4
4
|
// mirroring how Attio's window works. The sidebar pane clips (never squishes)
|
|
@@ -15,6 +15,8 @@ const config = defineRecipe({
|
|
|
15
15
|
& .appshell-main { position: relative; flex: 1; min-width: 0; display: flex; flex-direction: column; overflow: hidden; }
|
|
16
16
|
& .appshell-expand { position: absolute; top: ${c.space["2"]}; inset-inline-start: ${c.space["2"]}; z-index: 6; display: inline-flex; align-items: center; justify-content: center; width: ${c.size.row}; height: ${c.size.row}; padding: 0; border: none; border-radius: ${c.radius.md}; box-shadow: inset 0 0 0 1px ${c.borderSubtle}; background: ${c.bgSurface}; color: ${c.fgMuted}; font-family: inherit; cursor: pointer; transition: background-color .12s; }
|
|
17
17
|
& .appshell-expand:hover { background: ${c.bgRaised}; color: ${c.fgPrimary}; }
|
|
18
|
+
|
|
19
|
+
${rtlFlipCss}
|
|
18
20
|
`,
|
|
19
21
|
variants: {},
|
|
20
22
|
defaultVariants: {},
|
|
@@ -946,7 +946,7 @@ export function RecordsTable({ labels, columns: columnsProp = defaultColumns, ro
|
|
|
946
946
|
}
|
|
947
947
|
: undefined, onDragEnd: () => setDragCol(null), onClick: (e) => openColumnMenu(col.key, e.currentTarget), children: [Icon ? _jsx(Icon, { size: 14, strokeWidth: 1.75 }) : null, _jsx("span", { className: "recordstable-th-label", children: col.label }), _jsx("span", { className: "recordstable-sort", children: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", children: _jsx("path", { d: "m4 6 4 4 4-4" }) }) })] })), openMenu === `col:${col.key}` &&
|
|
948
948
|
rootRef.current &&
|
|
949
|
-
createPortal(_jsxs("div", { ref: menuRef, className: "recordstable-menu recordstable-menu--fixed recordstable-menu--hdr", role: "menu", "aria-label": `${col.label} column`, style: menuPos ?? undefined, onKeyDown: onMenuKeyDown, children: [_jsxs("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => sortBy(col.key, "asc"), children: [_jsx(ArrowUp, { size: 15, strokeWidth: 1.75 }), t.sortAscending] }), _jsxs("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => sortBy(col.key, "desc"), children: [_jsx(ArrowDown, { size: 15, strokeWidth: 1.75 }), t.sortDescending] }), _jsxs("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, disabled: i <= 1, onClick: () => moveColumn(col.key, -1), children: [_jsx(ArrowLeft, { size: 15, strokeWidth: 1.75 }), t.moveLeft] }), _jsxs("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, disabled: i === 0 || i >= cols.length - 1, onClick: () => moveColumn(col.key, 1), children: [_jsx(ArrowRight, { size: 15, strokeWidth: 1.75 }), t.moveRight] }), _jsx("div", { className: "recordstable-menu-sep" }), _jsxs("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => {
|
|
949
|
+
createPortal(_jsxs("div", { ref: menuRef, className: "recordstable-menu recordstable-menu--fixed recordstable-menu--hdr", role: "menu", "aria-label": `${col.label} column`, style: menuPos ?? undefined, onKeyDown: onMenuKeyDown, children: [_jsxs("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => sortBy(col.key, "asc"), children: [_jsx(ArrowUp, { size: 15, strokeWidth: 1.75 }), t.sortAscending] }), _jsxs("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => sortBy(col.key, "desc"), children: [_jsx(ArrowDown, { size: 15, strokeWidth: 1.75 }), t.sortDescending] }), _jsxs("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, disabled: i <= 1, onClick: () => moveColumn(col.key, -1), children: [_jsx(ArrowLeft, { "data-rtl-flip": "", size: 15, strokeWidth: 1.75 }), t.moveLeft] }), _jsxs("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, disabled: i === 0 || i >= cols.length - 1, onClick: () => moveColumn(col.key, 1), children: [_jsx(ArrowRight, { "data-rtl-flip": "", size: 15, strokeWidth: 1.75 }), t.moveRight] }), _jsx("div", { className: "recordstable-menu-sep" }), _jsxs("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => {
|
|
950
950
|
setRenamingCol(col.key);
|
|
951
951
|
setOpenMenu(null);
|
|
952
952
|
}, children: [_jsx(Pencil, { size: 15, strokeWidth: 1.75 }), t.editColumnLabel] }), cols.length > 1 && (_jsxs("button", { type: "button", className: "recordstable-menu-item", role: "menuitem", tabIndex: -1, onClick: () => hideColumn(col.key), children: [_jsx(EyeOff, { size: 15, strokeWidth: 1.75 }), t.hideFromView] }))] }), rootRef.current), _jsx("span", { className: "recordstable-resize", "aria-hidden": "true", onPointerDown: (e) => {
|
|
@@ -987,7 +987,7 @@ export function RecordsTable({ labels, columns: columnsProp = defaultColumns, ro
|
|
|
987
987
|
: undefined, avatarTone: avatarTone })), i === 0 && onOpenRecord && !isEditing && (_jsx("button", { type: "button", className: "recordstable-open", "aria-label": `Open ${cellText(col, row)}`, onClick: (e) => {
|
|
988
988
|
e.stopPropagation();
|
|
989
989
|
onOpenRecord(row);
|
|
990
|
-
}, children: _jsx(ArrowUpRight, { size: 15, strokeWidth: 1.75 }) }))] }, col.key));
|
|
990
|
+
}, children: _jsx(ArrowUpRight, { "data-rtl-flip": "", size: 15, strokeWidth: 1.75 }) }))] }, col.key));
|
|
991
991
|
}), _jsx("td", { className: "recordstable-td recordstable-addcol" })] }, row.id))) }), _jsx("tfoot", { children: _jsxs("tr", { children: [_jsx("td", { className: "recordstable-sum recordstable-col-check" }), cols.map((col, i) => {
|
|
992
992
|
const a = agg[col.key] ?? "none";
|
|
993
993
|
const res = summarize(col, a, visibleRows);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { toolbarChromeBody, toolbarChromeHead, } from "../../components/tabletoolbar/tabletoolbar.chrome.js";
|
|
2
|
-
import { defineRecipe, resolveRecipe } from "../../core/index.js";
|
|
2
|
+
import { defineRecipe, resolveRecipe, rtlFlipCss } from "../../core/index.js";
|
|
3
3
|
import { contract as c } from "../../tokens/index.js";
|
|
4
4
|
import { recordTagCss } from "./recordstable.tag.js";
|
|
5
5
|
// Attio's record grid, measured: 36px rows, 1px borderSubtle (#eeeff1) grid
|
|
@@ -142,6 +142,8 @@ ${toolbarChromeBody("recordstable")}
|
|
|
142
142
|
& .recordstable-bulk-sep { width: 1px; height: 20px; margin: 0 ${c.space["0.5"]}; background: ${c.borderSubtle}; }
|
|
143
143
|
& .recordstable-bulk-close { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: none; border-radius: ${c.radius.md}; background: transparent; color: ${c.fgMuted}; cursor: pointer; }
|
|
144
144
|
& .recordstable-bulk-close:hover { background: ${c.bgRaised}; color: ${c.fgPrimary}; }
|
|
145
|
+
|
|
146
|
+
${rtlFlipCss}
|
|
145
147
|
`,
|
|
146
148
|
variants: {},
|
|
147
149
|
defaultVariants: {},
|
|
@@ -18,6 +18,6 @@ export function SettingsShell({ title = "Settings", onBack, groups, activeItem,
|
|
|
18
18
|
}))
|
|
19
19
|
.filter((g) => g.items.length > 0)
|
|
20
20
|
: groups;
|
|
21
|
-
return (_jsxs("div", { className: settingsshellRecipe({ className }), ...rest, children: [_jsxs("nav", { className: "settingsshell-nav", "aria-label": navLabel, children: [_jsxs("button", { type: "button", className: "settingsshell-back", onClick: onBack, children: [_jsx(ChevronLeft, { size: 16, strokeWidth: 2 }), title] }), searchable && (_jsxs("div", { className: "settingsshell-search", children: [_jsx(Search, { size: 15, strokeWidth: 1.75 }), _jsx("input", { type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, value: query, onChange: (e) => setQuery(e.target.value) })] })), _jsx("div", { className: "settingsshell-groups", children: filtered.length === 0 ? (_jsx("div", { className: "settingsshell-empty", children: emptyLabel })) : (filtered.map((g, gi) => (_jsxs("div", { className: "settingsshell-group", children: [g.label != null && (_jsx("div", { className: "settingsshell-group-label", children: g.label })), g.items.map((it) => (_jsxs("button", { type: "button", className: "settingsshell-item", "aria-current": it.id === activeItem ? "page" : undefined, "data-active": it.id === activeItem ? "" : undefined, onClick: () => onSelect(it.id), children: [it.icon, _jsx("span", { className: "settingsshell-item-label", children: it.label })] }, it.id)))] }, gi)))) })] }), _jsx("div", { className: "settingsshell-content", children: children })] }));
|
|
21
|
+
return (_jsxs("div", { className: settingsshellRecipe({ className }), ...rest, children: [_jsxs("nav", { className: "settingsshell-nav", "aria-label": navLabel, children: [_jsxs("button", { type: "button", className: "settingsshell-back", onClick: onBack, children: [_jsx(ChevronLeft, { "data-rtl-flip": "", size: 16, strokeWidth: 2 }), title] }), searchable && (_jsxs("div", { className: "settingsshell-search", children: [_jsx(Search, { size: 15, strokeWidth: 1.75 }), _jsx("input", { type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, value: query, onChange: (e) => setQuery(e.target.value) })] })), _jsx("div", { className: "settingsshell-groups", children: filtered.length === 0 ? (_jsx("div", { className: "settingsshell-empty", children: emptyLabel })) : (filtered.map((g, gi) => (_jsxs("div", { className: "settingsshell-group", children: [g.label != null && (_jsx("div", { className: "settingsshell-group-label", children: g.label })), g.items.map((it) => (_jsxs("button", { type: "button", className: "settingsshell-item", "aria-current": it.id === activeItem ? "page" : undefined, "data-active": it.id === activeItem ? "" : undefined, onClick: () => onSelect(it.id), children: [it.icon, _jsx("span", { className: "settingsshell-item-label", children: it.label })] }, it.id)))] }, gi)))) })] }), _jsx("div", { className: "settingsshell-content", children: children })] }));
|
|
22
22
|
}
|
|
23
23
|
SettingsShell.displayName = "SettingsShell";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineRecipe, resolveRecipe } from "../../core/index.js";
|
|
1
|
+
import { defineRecipe, resolveRecipe, rtlFlipCss } from "../../core/index.js";
|
|
2
2
|
import { contract as c } from "../../tokens/index.js";
|
|
3
3
|
// The Settings layout — measured from Attio's Settings: a 256px left nav with a
|
|
4
4
|
// back header, a search field, and grouped nav items (active row raised), beside
|
|
@@ -34,7 +34,9 @@ const config = defineRecipe({
|
|
|
34
34
|
& .settingsshell-item[data-active] svg { color: ${c.fgPrimary}; }
|
|
35
35
|
& .settingsshell-empty { padding: ${c.space["3"]} ${c.space["2"]}; font-size: ${c.text.md}; color: ${c.fgMuted}; }
|
|
36
36
|
|
|
37
|
-
& .settingsshell-content { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; padding: ${c.space["6"]} ${c.space["8"]}; }
|
|
37
|
+
& .settingsshell-content { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; padding: ${c.space["6"]} ${c.space["8"]}; }
|
|
38
|
+
${rtlFlipCss}
|
|
39
|
+
`,
|
|
38
40
|
variants: {},
|
|
39
41
|
defaultVariants: {},
|
|
40
42
|
compoundVariants: [],
|
package/dist/recordstable.css
CHANGED
|
@@ -198,6 +198,8 @@
|
|
|
198
198
|
& .recordstable-bulk-close { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: none; border-radius: var(--radius-md); background: transparent; color: var(--fg-muted); cursor: pointer; }
|
|
199
199
|
& .recordstable-bulk-close:hover { background: var(--bg-raised); color: var(--fg-primary); }
|
|
200
200
|
|
|
201
|
+
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
202
|
+
|
|
201
203
|
}
|
|
202
204
|
|
|
203
205
|
@media (prefers-reduced-motion: reduce) {
|
package/dist/settingsshell.css
CHANGED
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
& .settingsshell-empty { padding: var(--space-3) var(--space-2); font-size: var(--text-md); color: var(--fg-muted); }
|
|
30
30
|
|
|
31
31
|
& .settingsshell-content { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; padding: var(--space-6) var(--space-8); }
|
|
32
|
+
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
33
|
+
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
@media (prefers-reduced-motion: reduce) {
|
package/dist/slider.css
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
.slider {
|
|
2
|
+
|
|
3
|
+
display: flex; flex-direction: column; align-items: stretch;
|
|
4
|
+
width: 100%; min-width: 0; gap: var(--space-0-5);
|
|
5
|
+
font-family: var(--font-sans); user-select: none; touch-action: none;
|
|
6
|
+
|
|
7
|
+
& .slider-control { position: relative; height: 26px; display: flex; align-items: center; }
|
|
8
|
+
|
|
9
|
+
& .slider-track {
|
|
10
|
+
position: relative; flex-grow: 1; height: var(--space-1);
|
|
11
|
+
border-radius: var(--radius-full); background: var(--bg-neutral-weak);
|
|
12
|
+
overflow: hidden;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
& .slider-range { position: absolute; height: 100%; background: var(--bg-brand-solid); }
|
|
16
|
+
& .slider-range[data-dir="ltr"] { left: var(--range-start); right: var(--range-end); }
|
|
17
|
+
& .slider-range[data-dir="rtl"] { right: var(--range-start); left: var(--range-end); }
|
|
18
|
+
|
|
19
|
+
& .slider-thumb {
|
|
20
|
+
position: absolute; top: 50%;
|
|
21
|
+
width: var(--space-5); height: var(--space-5);
|
|
22
|
+
transform: translate(-50%, -50%);
|
|
23
|
+
border: none; background: none; padding: 0;
|
|
24
|
+
}
|
|
25
|
+
& .slider-thumb[data-dir="ltr"] { left: calc(var(--thumb-position) * 1% + var(--thumb-offset)); }
|
|
26
|
+
& .slider-thumb[data-dir="rtl"] { right: calc(var(--thumb-position) * 1% + var(--thumb-offset)); }
|
|
27
|
+
& .slider-thumb::after {
|
|
28
|
+
content: ""; position: absolute; inset: 0;
|
|
29
|
+
border-radius: var(--radius-full); background: #fff; box-shadow: inset 0 0 0 1px var(--ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04);
|
|
30
|
+
outline: 2px solid transparent; outline-offset: 2px;
|
|
31
|
+
transition: transform .2s ease, outline-color .2s ease;
|
|
32
|
+
cursor: grab;
|
|
33
|
+
}
|
|
34
|
+
& .slider-thumb[data-thumb-dragging]::after { transform: scale(1.2); cursor: grabbing; }
|
|
35
|
+
& .slider-thumb:focus { outline: none; }
|
|
36
|
+
& .slider-thumb:focus-visible::after { outline-color: var(--stroke-focus-ring); }
|
|
37
|
+
|
|
38
|
+
&[data-disabled] { cursor: not-allowed; }
|
|
39
|
+
&[data-disabled] .slider-range { background: var(--fg-disabled); }
|
|
40
|
+
&[data-disabled] .slider-thumb::after { cursor: not-allowed; }
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@media (prefers-reduced-motion: reduce) {
|
|
45
|
+
.slider, .slider * {
|
|
46
|
+
animation-duration: 0.01ms !important;
|
|
47
|
+
animation-iteration-count: 1 !important;
|
|
48
|
+
transition-duration: 0.01ms !important;
|
|
49
|
+
}
|
|
50
|
+
}
|
package/dist/slider.d.ts
ADDED
package/dist/styles.css
CHANGED
|
@@ -272,6 +272,8 @@
|
|
|
272
272
|
& button.breadcrumb-item { border: none; background: none; font: inherit; cursor: pointer; }
|
|
273
273
|
& .breadcrumb-item[aria-current] { color: var(--fg-primary); font-weight: var(--weight-medium); }
|
|
274
274
|
& .breadcrumb-sep { flex-shrink: 0; color: color-mix(in srgb, var(--fg-primary) 28%, transparent); }
|
|
275
|
+
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
276
|
+
|
|
275
277
|
}
|
|
276
278
|
|
|
277
279
|
.bulkbar {
|
|
@@ -1363,6 +1365,57 @@
|
|
|
1363
1365
|
}
|
|
1364
1366
|
}
|
|
1365
1367
|
|
|
1368
|
+
.slider {
|
|
1369
|
+
|
|
1370
|
+
display: flex; flex-direction: column; align-items: stretch;
|
|
1371
|
+
width: 100%; min-width: 0; gap: var(--space-0-5);
|
|
1372
|
+
font-family: var(--font-sans); user-select: none; touch-action: none;
|
|
1373
|
+
|
|
1374
|
+
& .slider-control { position: relative; height: 26px; display: flex; align-items: center; }
|
|
1375
|
+
|
|
1376
|
+
& .slider-track {
|
|
1377
|
+
position: relative; flex-grow: 1; height: var(--space-1);
|
|
1378
|
+
border-radius: var(--radius-full); background: var(--bg-neutral-weak);
|
|
1379
|
+
overflow: hidden;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
& .slider-range { position: absolute; height: 100%; background: var(--bg-brand-solid); }
|
|
1383
|
+
& .slider-range[data-dir="ltr"] { left: var(--range-start); right: var(--range-end); }
|
|
1384
|
+
& .slider-range[data-dir="rtl"] { right: var(--range-start); left: var(--range-end); }
|
|
1385
|
+
|
|
1386
|
+
& .slider-thumb {
|
|
1387
|
+
position: absolute; top: 50%;
|
|
1388
|
+
width: var(--space-5); height: var(--space-5);
|
|
1389
|
+
transform: translate(-50%, -50%);
|
|
1390
|
+
border: none; background: none; padding: 0;
|
|
1391
|
+
}
|
|
1392
|
+
& .slider-thumb[data-dir="ltr"] { left: calc(var(--thumb-position) * 1% + var(--thumb-offset)); }
|
|
1393
|
+
& .slider-thumb[data-dir="rtl"] { right: calc(var(--thumb-position) * 1% + var(--thumb-offset)); }
|
|
1394
|
+
& .slider-thumb::after {
|
|
1395
|
+
content: ""; position: absolute; inset: 0;
|
|
1396
|
+
border-radius: var(--radius-full); background: #fff; box-shadow: inset 0 0 0 1px var(--ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04);
|
|
1397
|
+
outline: 2px solid transparent; outline-offset: 2px;
|
|
1398
|
+
transition: transform .2s ease, outline-color .2s ease;
|
|
1399
|
+
cursor: grab;
|
|
1400
|
+
}
|
|
1401
|
+
& .slider-thumb[data-thumb-dragging]::after { transform: scale(1.2); cursor: grabbing; }
|
|
1402
|
+
& .slider-thumb:focus { outline: none; }
|
|
1403
|
+
& .slider-thumb:focus-visible::after { outline-color: var(--stroke-focus-ring); }
|
|
1404
|
+
|
|
1405
|
+
&[data-disabled] { cursor: not-allowed; }
|
|
1406
|
+
&[data-disabled] .slider-range { background: var(--fg-disabled); }
|
|
1407
|
+
&[data-disabled] .slider-thumb::after { cursor: not-allowed; }
|
|
1408
|
+
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1412
|
+
.slider, .slider * {
|
|
1413
|
+
animation-duration: 0.01ms !important;
|
|
1414
|
+
animation-iteration-count: 1 !important;
|
|
1415
|
+
transition-duration: 0.01ms !important;
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1366
1419
|
@keyframes crisp-spin { to { transform: rotate(360deg); } }
|
|
1367
1420
|
.spinner {
|
|
1368
1421
|
display: inline-block; box-sizing: border-box; width: 16px; height: 16px; border-radius: var(--radius-full); border: 2px solid color-mix(in srgb, var(--fg-primary) 15%, transparent); border-top-color: var(--fg-muted); animation: crisp-spin 0.6s linear infinite;
|
|
@@ -1732,6 +1785,8 @@
|
|
|
1732
1785
|
& .appshell-expand { position: absolute; top: var(--space-2); inset-inline-start: var(--space-2); z-index: 6; display: inline-flex; align-items: center; justify-content: center; width: var(--size-row); height: var(--size-row); padding: 0; border: none; border-radius: var(--radius-md); box-shadow: inset 0 0 0 1px var(--border-subtle); background: var(--bg-surface); color: var(--fg-muted); font-family: inherit; cursor: pointer; transition: background-color .12s; }
|
|
1733
1786
|
& .appshell-expand:hover { background: var(--bg-raised); color: var(--fg-primary); }
|
|
1734
1787
|
|
|
1788
|
+
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
1789
|
+
|
|
1735
1790
|
}
|
|
1736
1791
|
|
|
1737
1792
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -2449,6 +2504,8 @@
|
|
|
2449
2504
|
& .recordstable-bulk-close { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: none; border-radius: var(--radius-md); background: transparent; color: var(--fg-muted); cursor: pointer; }
|
|
2450
2505
|
& .recordstable-bulk-close:hover { background: var(--bg-raised); color: var(--fg-primary); }
|
|
2451
2506
|
|
|
2507
|
+
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
2508
|
+
|
|
2452
2509
|
}
|
|
2453
2510
|
|
|
2454
2511
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -2537,6 +2594,8 @@
|
|
|
2537
2594
|
& .settingsshell-empty { padding: var(--space-3) var(--space-2); font-size: var(--text-md); color: var(--fg-muted); }
|
|
2538
2595
|
|
|
2539
2596
|
& .settingsshell-content { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; padding: var(--space-6) var(--space-8); }
|
|
2597
|
+
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
2598
|
+
|
|
2540
2599
|
}
|
|
2541
2600
|
|
|
2542
2601
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type SliderRootProps } from "@seed-design/react-slider";
|
|
2
|
+
export type SliderProps = SliderRootProps;
|
|
3
|
+
/**
|
|
4
|
+
* A range input, driven by seed-design's headless engine so the keyboard model,
|
|
5
|
+
* the pointer maths and multi-thumb constraints are theirs by construction.
|
|
6
|
+
* Pass one value for a simple slider, two for a range.
|
|
7
|
+
*/
|
|
8
|
+
export declare function Slider({ className, ...props }: SliderProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mirroring for direction-bearing icons.
|
|
3
|
+
*
|
|
4
|
+
* A chevron or arrow that means "back", "next", "toward the start" or "open"
|
|
5
|
+
* points the wrong way under RTL, and unlike spacing or alignment it cannot be
|
|
6
|
+
* fixed with a logical property: these are `lucide-react` nodes, static SVG
|
|
7
|
+
* paths with no direction of their own.
|
|
8
|
+
*
|
|
9
|
+
* Mark the icons that carry a direction with `data-rtl-flip` and include this
|
|
10
|
+
* snippet in the recipe. Icons whose meaning is NOT directional — a downward
|
|
11
|
+
* disclosure chevron, a search glass, a check — must be left unmarked: flipping
|
|
12
|
+
* them is a regression, not a fix.
|
|
13
|
+
*/
|
|
14
|
+
export declare const rtlFlipCss = "[dir=\"rtl\"] & [data-rtl-flip] { transform: scaleX(-1); }";
|
package/dist/types/index.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ export * from "./components/resizablepanel";
|
|
|
33
33
|
export * from "./components/segmented";
|
|
34
34
|
export * from "./components/select";
|
|
35
35
|
export * from "./components/skeleton";
|
|
36
|
+
export * from "./components/slider";
|
|
36
37
|
export * from "./components/spinner";
|
|
37
38
|
export * from "./components/stagebar";
|
|
38
39
|
export * from "./components/statcard";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crisp-ui-kit/crisp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "A lean React design system, measured pixel-for-pixel from Attio.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -207,6 +207,11 @@
|
|
|
207
207
|
"import": "./dist/esm/components/skeleton/index.js",
|
|
208
208
|
"require": "./dist/cjs/components/skeleton/index.js"
|
|
209
209
|
},
|
|
210
|
+
"./slider": {
|
|
211
|
+
"types": "./dist/types/components/slider/index.d.ts",
|
|
212
|
+
"import": "./dist/esm/components/slider/index.js",
|
|
213
|
+
"require": "./dist/cjs/components/slider/index.js"
|
|
214
|
+
},
|
|
210
215
|
"./spinner": {
|
|
211
216
|
"types": "./dist/types/components/spinner/index.d.ts",
|
|
212
217
|
"import": "./dist/esm/components/spinner/index.js",
|
|
@@ -418,6 +423,7 @@
|
|
|
418
423
|
"@seed-design/dom-utils": "^2.1.0",
|
|
419
424
|
"@seed-design/react-date-picker": "1.2.0",
|
|
420
425
|
"@seed-design/react-file-upload": "1.0.1",
|
|
426
|
+
"@seed-design/react-slider": "2.0.1",
|
|
421
427
|
"@seed-design/react-time-picker": "1.0.0",
|
|
422
428
|
"@zag-js/combobox": "^1.43.3",
|
|
423
429
|
"@zag-js/dialog": "^1.43.3",
|