@crisp-ui-kit/crisp 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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/timepicker/index.js +17 -0
- package/dist/cjs/components/timepicker/timepicker.js +54 -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/timepicker/index.js +1 -0
- package/dist/esm/components/timepicker/timepicker.js +51 -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/styles.css +8 -0
- package/dist/types/components/timepicker/index.d.ts +1 -0
- package/dist/types/components/timepicker/timepicker.d.ts +15 -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,17 @@
|
|
|
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("./timepicker"), exports);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.TimePicker = TimePicker;
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const react_time_picker_1 = require("@seed-design/react-time-picker");
|
|
7
|
+
const wheelpicker_1 = require("../wheelpicker");
|
|
8
|
+
const defaultLabels = {
|
|
9
|
+
period: "AM/PM",
|
|
10
|
+
hour: "Hour",
|
|
11
|
+
minute: "Minute",
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* An hour/minute wheel, driven by seed-design's headless engine so the column
|
|
15
|
+
* order, the 12- vs 24-hour split and the minute stepping are locale-correct by
|
|
16
|
+
* construction, and rendered with crisp's own `WheelPicker` so the pixels are
|
|
17
|
+
* the ones already measured for it.
|
|
18
|
+
*/
|
|
19
|
+
function TimePicker({ value, defaultValue, onValueChange, minuteStep, locale, disabled, labels, size = "medium", className, ...rest }) {
|
|
20
|
+
// The engine defaults `locale` to "ko-KR" — it is a Korean design system.
|
|
21
|
+
// crisp's other components are English-default, so the default is overridden
|
|
22
|
+
// here rather than inherited; a consumer's own `locale` still wins.
|
|
23
|
+
const api = (0, react_time_picker_1.useTimePicker)({
|
|
24
|
+
value,
|
|
25
|
+
defaultValue,
|
|
26
|
+
onValueChange,
|
|
27
|
+
minuteStep,
|
|
28
|
+
locale: locale ?? "en-US",
|
|
29
|
+
disabled,
|
|
30
|
+
});
|
|
31
|
+
const t = { ...defaultLabels, ...labels };
|
|
32
|
+
// `columnOrder` is locale-derived: en-US puts the period last ("3:30 PM"),
|
|
33
|
+
// ko-KR first, and a 24-hour locale omits it entirely.
|
|
34
|
+
const columns = api.columnOrder.map((type) => ({
|
|
35
|
+
key: type,
|
|
36
|
+
label: t[type],
|
|
37
|
+
options: api.columns[type].options.map((o) => ({
|
|
38
|
+
value: o.value,
|
|
39
|
+
label: o.label,
|
|
40
|
+
})),
|
|
41
|
+
}));
|
|
42
|
+
const selection = Object.fromEntries(api.columnOrder.map((type) => [type, api.columns[type].value]));
|
|
43
|
+
return ((0, jsx_runtime_1.jsx)("div", { ...rest, className: className, children: (0, jsx_runtime_1.jsx)(wheelpicker_1.WheelPicker, { columns: columns, value: selection, size: size, onValueChange: (next) => {
|
|
44
|
+
// Route each wheel back to its OWN column, so the engine keeps
|
|
45
|
+
// ownership of rounding, looping and the 12-to-24-hour mapping.
|
|
46
|
+
// Sending them all to one column silently makes the period wheel
|
|
47
|
+
// set the hour.
|
|
48
|
+
for (const type of api.columnOrder) {
|
|
49
|
+
const v = next[type];
|
|
50
|
+
if (v != null)
|
|
51
|
+
api.columns[type].onValueChange(v);
|
|
52
|
+
}
|
|
53
|
+
} }) }));
|
|
54
|
+
}
|
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
|
@@ -61,6 +61,7 @@ __exportStar(require("./components/table"), exports);
|
|
|
61
61
|
__exportStar(require("./components/tabletoolbar"), exports);
|
|
62
62
|
__exportStar(require("./components/tabs"), exports);
|
|
63
63
|
__exportStar(require("./components/textarea"), exports);
|
|
64
|
+
__exportStar(require("./components/timepicker"), exports);
|
|
64
65
|
__exportStar(require("./components/toast"), exports);
|
|
65
66
|
__exportStar(require("./components/tooltip"), exports);
|
|
66
67
|
__exportStar(require("./components/wheelpicker"), 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 @@
|
|
|
1
|
+
export * from "./timepicker.js";
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useTimePicker, } from "@seed-design/react-time-picker";
|
|
4
|
+
import { WheelPicker } from "../wheelpicker/index.js";
|
|
5
|
+
const defaultLabels = {
|
|
6
|
+
period: "AM/PM",
|
|
7
|
+
hour: "Hour",
|
|
8
|
+
minute: "Minute",
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* An hour/minute wheel, driven by seed-design's headless engine so the column
|
|
12
|
+
* order, the 12- vs 24-hour split and the minute stepping are locale-correct by
|
|
13
|
+
* construction, and rendered with crisp's own `WheelPicker` so the pixels are
|
|
14
|
+
* the ones already measured for it.
|
|
15
|
+
*/
|
|
16
|
+
export function TimePicker({ value, defaultValue, onValueChange, minuteStep, locale, disabled, labels, size = "medium", className, ...rest }) {
|
|
17
|
+
// The engine defaults `locale` to "ko-KR" — it is a Korean design system.
|
|
18
|
+
// crisp's other components are English-default, so the default is overridden
|
|
19
|
+
// here rather than inherited; a consumer's own `locale` still wins.
|
|
20
|
+
const api = useTimePicker({
|
|
21
|
+
value,
|
|
22
|
+
defaultValue,
|
|
23
|
+
onValueChange,
|
|
24
|
+
minuteStep,
|
|
25
|
+
locale: locale ?? "en-US",
|
|
26
|
+
disabled,
|
|
27
|
+
});
|
|
28
|
+
const t = { ...defaultLabels, ...labels };
|
|
29
|
+
// `columnOrder` is locale-derived: en-US puts the period last ("3:30 PM"),
|
|
30
|
+
// ko-KR first, and a 24-hour locale omits it entirely.
|
|
31
|
+
const columns = api.columnOrder.map((type) => ({
|
|
32
|
+
key: type,
|
|
33
|
+
label: t[type],
|
|
34
|
+
options: api.columns[type].options.map((o) => ({
|
|
35
|
+
value: o.value,
|
|
36
|
+
label: o.label,
|
|
37
|
+
})),
|
|
38
|
+
}));
|
|
39
|
+
const selection = Object.fromEntries(api.columnOrder.map((type) => [type, api.columns[type].value]));
|
|
40
|
+
return (_jsx("div", { ...rest, className: className, children: _jsx(WheelPicker, { columns: columns, value: selection, size: size, onValueChange: (next) => {
|
|
41
|
+
// Route each wheel back to its OWN column, so the engine keeps
|
|
42
|
+
// ownership of rounding, looping and the 12-to-24-hour mapping.
|
|
43
|
+
// Sending them all to one column silently makes the period wheel
|
|
44
|
+
// set the hour.
|
|
45
|
+
for (const type of api.columnOrder) {
|
|
46
|
+
const v = next[type];
|
|
47
|
+
if (v != null)
|
|
48
|
+
api.columns[type].onValueChange(v);
|
|
49
|
+
}
|
|
50
|
+
} }) }));
|
|
51
|
+
}
|
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
|
@@ -45,6 +45,7 @@ export * from "./components/table/index.js";
|
|
|
45
45
|
export * from "./components/tabletoolbar/index.js";
|
|
46
46
|
export * from "./components/tabs/index.js";
|
|
47
47
|
export * from "./components/textarea/index.js";
|
|
48
|
+
export * from "./components/timepicker/index.js";
|
|
48
49
|
export * from "./components/toast/index.js";
|
|
49
50
|
export * from "./components/tooltip/index.js";
|
|
50
51
|
export * from "./components/wheelpicker/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/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 {
|
|
@@ -1732,6 +1734,8 @@
|
|
|
1732
1734
|
& .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
1735
|
& .appshell-expand:hover { background: var(--bg-raised); color: var(--fg-primary); }
|
|
1734
1736
|
|
|
1737
|
+
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
1738
|
+
|
|
1735
1739
|
}
|
|
1736
1740
|
|
|
1737
1741
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -2449,6 +2453,8 @@
|
|
|
2449
2453
|
& .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
2454
|
& .recordstable-bulk-close:hover { background: var(--bg-raised); color: var(--fg-primary); }
|
|
2451
2455
|
|
|
2456
|
+
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
2457
|
+
|
|
2452
2458
|
}
|
|
2453
2459
|
|
|
2454
2460
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -2537,6 +2543,8 @@
|
|
|
2537
2543
|
& .settingsshell-empty { padding: var(--space-3) var(--space-2); font-size: var(--text-md); color: var(--fg-muted); }
|
|
2538
2544
|
|
|
2539
2545
|
& .settingsshell-content { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; padding: var(--space-6) var(--space-8); }
|
|
2546
|
+
[dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
|
|
2547
|
+
|
|
2540
2548
|
}
|
|
2541
2549
|
|
|
2542
2550
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./timepicker";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type MinuteStep, type TimePickerValue, type UseTimePickerProps } from "@seed-design/react-time-picker";
|
|
2
|
+
import type * as React from "react";
|
|
3
|
+
export type { MinuteStep, TimePickerValue };
|
|
4
|
+
export type TimePickerProps = UseTimePickerProps & Omit<React.ComponentPropsWithoutRef<"div">, keyof UseTimePickerProps | "children"> & {
|
|
5
|
+
/** Accessible names for the wheels, so they can be translated. */
|
|
6
|
+
labels?: Partial<Record<"period" | "hour" | "minute", string>>;
|
|
7
|
+
size?: "small" | "medium";
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* An hour/minute wheel, driven by seed-design's headless engine so the column
|
|
11
|
+
* order, the 12- vs 24-hour split and the minute stepping are locale-correct by
|
|
12
|
+
* construction, and rendered with crisp's own `WheelPicker` so the pixels are
|
|
13
|
+
* the ones already measured for it.
|
|
14
|
+
*/
|
|
15
|
+
export declare function TimePicker({ value, defaultValue, onValueChange, minuteStep, locale, disabled, labels, size, className, ...rest }: TimePickerProps): 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
|
@@ -41,6 +41,7 @@ export * from "./components/table";
|
|
|
41
41
|
export * from "./components/tabletoolbar";
|
|
42
42
|
export * from "./components/tabs";
|
|
43
43
|
export * from "./components/textarea";
|
|
44
|
+
export * from "./components/timepicker";
|
|
44
45
|
export * from "./components/toast";
|
|
45
46
|
export * from "./components/tooltip";
|
|
46
47
|
export * from "./components/wheelpicker";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crisp-ui-kit/crisp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "A lean React design system, measured pixel-for-pixel from Attio.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -247,6 +247,11 @@
|
|
|
247
247
|
"import": "./dist/esm/components/textarea/index.js",
|
|
248
248
|
"require": "./dist/cjs/components/textarea/index.js"
|
|
249
249
|
},
|
|
250
|
+
"./timepicker": {
|
|
251
|
+
"types": "./dist/types/components/timepicker/index.d.ts",
|
|
252
|
+
"import": "./dist/esm/components/timepicker/index.js",
|
|
253
|
+
"require": "./dist/cjs/components/timepicker/index.js"
|
|
254
|
+
},
|
|
250
255
|
"./toast": {
|
|
251
256
|
"types": "./dist/types/components/toast/index.d.ts",
|
|
252
257
|
"import": "./dist/esm/components/toast/index.js",
|
|
@@ -413,6 +418,7 @@
|
|
|
413
418
|
"@seed-design/dom-utils": "^2.1.0",
|
|
414
419
|
"@seed-design/react-date-picker": "1.2.0",
|
|
415
420
|
"@seed-design/react-file-upload": "1.0.1",
|
|
421
|
+
"@seed-design/react-time-picker": "1.0.0",
|
|
416
422
|
"@zag-js/combobox": "^1.43.3",
|
|
417
423
|
"@zag-js/dialog": "^1.43.3",
|
|
418
424
|
"@zag-js/react": "^1.43.3",
|