@wallarm-org/design-system 0.88.0 → 0.88.1-rc-fix-status-code-zero-value.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/components/FilterInput/lib/statusCode/createStatusCodeNormalizer.d.ts +3 -1
- package/dist/components/FilterInput/lib/statusCode/createStatusCodeNormalizer.js +2 -0
- package/dist/components/FilterInput/lib/statusCode/createStatusCodeSerializer.d.ts +3 -1
- package/dist/components/FilterInput/lib/statusCode/createStatusCodeSerializer.js +2 -0
- package/dist/components/FilterInput/lib/statusCode/createStatusCodeSuggestions.js +2 -2
- package/dist/components/FilterInput/lib/statusCode/createStatusCodeValidator.d.ts +4 -0
- package/dist/components/FilterInput/lib/statusCode/createStatusCodeValidator.js +2 -1
- package/dist/components/FilterInput/lib/statusCode/utils/constants.d.ts +6 -0
- package/dist/components/FilterInput/lib/statusCode/utils/constants.js +2 -1
- package/dist/components/FilterInput/lib/statusCode/utils/index.d.ts +1 -1
- package/dist/components/FilterInput/lib/statusCode/utils/index.js +1 -1
- package/dist/components/FilterInput/lib/statusCode/utils/makeMask.d.ts +3 -1
- package/dist/components/FilterInput/lib/statusCode/utils/makeMask.js +12 -1
- package/dist/components/Table/EditableCell/EditableSelectCell.d.ts +28 -0
- package/dist/components/Table/EditableCell/EditableSelectCell.js +66 -0
- package/dist/components/Table/EditableCell/EditableTextCell.d.ts +22 -0
- package/dist/components/Table/EditableCell/EditableTextCell.js +78 -0
- package/dist/components/Table/EditableCell/classes.d.ts +11 -0
- package/dist/components/Table/EditableCell/classes.js +17 -0
- package/dist/components/Table/EditableCell/constants.d.ts +19 -0
- package/dist/components/Table/EditableCell/constants.js +4 -0
- package/dist/components/Table/EditableCell/index.d.ts +4 -0
- package/dist/components/Table/EditableCell/index.js +4 -0
- package/dist/components/Table/index.d.ts +1 -0
- package/dist/components/Table/index.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/metadata/components.json +768 -190
- package/package.json +1 -1
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* - "22" → "22X"
|
|
6
6
|
* - "2x" → "2XX"
|
|
7
7
|
* - "222", "4XX", "40X" → unchanged (already 3 chars)
|
|
8
|
-
* Leaves anything unrecognised alone so `validate` can still flag it.
|
|
8
|
+
* Leaves anything unrecognised alone so `validate` can still flag it. The
|
|
9
|
+
* `NO_RESPONSE_CODE` sentinel (`"0"`) is a concrete value, not a partial class,
|
|
10
|
+
* so it is passed through as-is rather than padded to `"0XX"`.
|
|
9
11
|
*/
|
|
10
12
|
export declare const createStatusCodeNormalizer: () => ((value: string | number | boolean) => string | number | boolean);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { NO_RESPONSE_CODE } from "./utils/constants.js";
|
|
1
2
|
const createStatusCodeNormalizer = ()=>(value)=>{
|
|
2
3
|
if ('string' != typeof value && 'number' != typeof value) return value;
|
|
3
4
|
const s = String(value).toUpperCase();
|
|
5
|
+
if (s === NO_RESPONSE_CODE) return s;
|
|
4
6
|
if (!/^\d[0-9X]{0,2}$/.test(s)) return value;
|
|
5
7
|
if (1 === s.length) return `${s}XX`;
|
|
6
8
|
if (2 === s.length) return `${s}X`;
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Anything that isn't a status-code-shaped string (e.g. a number, boolean,
|
|
13
13
|
* or freeform text) is returned unchanged so invalid committed values still
|
|
14
|
-
* surface in the backend payload for the parser to reject.
|
|
14
|
+
* surface in the backend payload for the parser to reject. The
|
|
15
|
+
* `NO_RESPONSE_CODE` sentinel (`"0"`) carries no mask placeholder, so it is
|
|
16
|
+
* passed through verbatim.
|
|
15
17
|
*/
|
|
16
18
|
export declare const createStatusCodeSerializer: () => ((value: string | number | boolean) => string | number | boolean);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { NO_RESPONSE_CODE } from "./utils/constants.js";
|
|
1
2
|
const createStatusCodeSerializer = ()=>(value)=>{
|
|
2
3
|
if ('string' != typeof value) return value;
|
|
4
|
+
if (value === NO_RESPONSE_CODE) return value;
|
|
3
5
|
if (!/^\d[\dX]{0,2}$/i.test(value)) return value;
|
|
4
6
|
return value.replace(/X+$/i, '');
|
|
5
7
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { MASK_ROOTS, canonicalizeStatusCodeInput, makeMask } from "./utils/index.js";
|
|
1
|
+
import { MASK_ROOTS, NO_RESPONSE_CODE, canonicalizeStatusCodeInput, makeMask } from "./utils/index.js";
|
|
2
2
|
const createStatusCodeSuggestions = ()=>{
|
|
3
|
-
const resolveSelected = (selectedValues)=>(selectedValues ?? []).map((v)=>String(v)).filter((s)
|
|
3
|
+
const resolveSelected = (selectedValues)=>(selectedValues ?? []).map((v)=>String(v)).filter((s)=>s === NO_RESPONSE_CODE || /^\d[\dX]{0,2}$/.test(s) && MASK_ROOTS.includes(s.charAt(0))).map((s)=>makeMask(s));
|
|
4
4
|
return (inputText, context)=>{
|
|
5
5
|
const norm = inputText.trim();
|
|
6
6
|
const selected = resolveSelected(context?.selectedValues);
|
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
* - `dX` (narrowed mask like `40X`)
|
|
7
7
|
* - `dd` (concrete code like `401`)
|
|
8
8
|
*
|
|
9
|
+
* The `NO_RESPONSE_CODE` sentinel (`status_code=0`, published by the backend
|
|
10
|
+
* for attacks with no HTTP response) is also accepted even though it carries no
|
|
11
|
+
* HTTP class.
|
|
12
|
+
*
|
|
9
13
|
* Returns `true` when the value is invalid, matching the
|
|
10
14
|
* `FieldMetadata.validate` contract.
|
|
11
15
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { MASK_ROOTS, STATUS_CODE_LENGTH } from "./utils/index.js";
|
|
1
|
+
import { MASK_ROOTS, NO_RESPONSE_CODE, STATUS_CODE_LENGTH } from "./utils/index.js";
|
|
2
2
|
const createStatusCodeValidator = ()=>(value)=>{
|
|
3
3
|
const s = String(value);
|
|
4
|
+
if (s === NO_RESPONSE_CODE) return false;
|
|
4
5
|
if (s.length !== STATUS_CODE_LENGTH) return true;
|
|
5
6
|
if (!MASK_ROOTS.includes(s.charAt(0))) return true;
|
|
6
7
|
return !/^(XX|\dX|\d\d)$/.test(s.slice(1));
|
|
@@ -11,3 +11,9 @@ export declare const MASK_ROOTS: readonly string[];
|
|
|
11
11
|
export declare const STATUS_CODE_LENGTH = 3;
|
|
12
12
|
/** Placeholder character used inside masks (e.g. the `X` in `4XX`). */
|
|
13
13
|
export declare const MASK_PLACEHOLDER = "X";
|
|
14
|
+
/** The "no HTTP response captured" sentinel. The backend publishes
|
|
15
|
+
* `status_code=0` for attacks it never got a response for; it is a legitimate,
|
|
16
|
+
* filterable concrete value that sits outside the `1XX–5XX` HTTP classes, so
|
|
17
|
+
* the mask helpers treat it as a valid, neutrally-badged code rather than an
|
|
18
|
+
* incomplete class or an error. */
|
|
19
|
+
export declare const NO_RESPONSE_CODE = "0";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { canonicalizeStatusCodeInput } from './canonicalize';
|
|
2
|
-
export { MASK_PLACEHOLDER, MASK_ROOTS, STATUS_CODE_LENGTH } from './constants';
|
|
2
|
+
export { MASK_PLACEHOLDER, MASK_ROOTS, NO_RESPONSE_CODE, STATUS_CODE_LENGTH } from './constants';
|
|
3
3
|
export { makeMask } from './makeMask';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { canonicalizeStatusCodeInput } from "./canonicalize.js";
|
|
2
|
-
export { MASK_PLACEHOLDER, MASK_ROOTS, STATUS_CODE_LENGTH } from "./constants.js";
|
|
2
|
+
export { MASK_PLACEHOLDER, MASK_ROOTS, NO_RESPONSE_CODE, STATUS_CODE_LENGTH } from "./constants.js";
|
|
3
3
|
export { makeMask } from "./makeMask.js";
|
|
@@ -4,5 +4,7 @@ import type { FieldValueOption } from '../../../types';
|
|
|
4
4
|
* in sync. Throws if the input falls outside the 1XX–5XX classes — this is
|
|
5
5
|
* unreachable in practice because callers gate on `maskRoots`, but the check
|
|
6
6
|
* is kept as a safety net so a future refactor can't silently emit a
|
|
7
|
-
* colorless pill.
|
|
7
|
+
* colorless pill. The one deliberate exception is the `NO_RESPONSE_CODE`
|
|
8
|
+
* sentinel, which is a legitimate value with no HTTP class and renders as a
|
|
9
|
+
* neutral slate pill. */
|
|
8
10
|
export declare const makeMask: (label: string) => FieldValueOption;
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import { RESPONSE_CODE_COLOR, getResponseCodeCategory } from "../../../../ResponseCode/index.js";
|
|
2
|
+
import { NO_RESPONSE_CODE } from "./constants.js";
|
|
2
3
|
const makeMask = (label)=>{
|
|
3
4
|
const category = getResponseCodeCategory(label);
|
|
4
|
-
if ('unknown' === category)
|
|
5
|
+
if ('unknown' === category) {
|
|
6
|
+
if (label === NO_RESPONSE_CODE) return {
|
|
7
|
+
value: label,
|
|
8
|
+
label,
|
|
9
|
+
badge: {
|
|
10
|
+
color: RESPONSE_CODE_COLOR.unknown,
|
|
11
|
+
text: label
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
throw new Error(`statusCode: no badge color for mask "${label}"`);
|
|
15
|
+
}
|
|
5
16
|
return {
|
|
6
17
|
value: label,
|
|
7
18
|
label,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { FC, HTMLAttributes, ReactNode, Ref } from 'react';
|
|
2
|
+
import { type TestableProps } from '../../../utils/testId';
|
|
3
|
+
import { type SelectDataItem } from '../../Select';
|
|
4
|
+
type NativeProps = Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'onChange'>;
|
|
5
|
+
export interface EditableSelectCellProps extends NativeProps, TestableProps {
|
|
6
|
+
/** Current committed value; `null` / `''` renders the placeholder. */
|
|
7
|
+
value: string | null;
|
|
8
|
+
/** Called with the picked value when the selection changes. */
|
|
9
|
+
onCommit: (value: string) => void;
|
|
10
|
+
/** Options for the dropdown. */
|
|
11
|
+
items: SelectDataItem[];
|
|
12
|
+
/** Read-mode rendering of the selected value (e.g. a `Badge`). */
|
|
13
|
+
children?: ReactNode;
|
|
14
|
+
/** Shown when nothing is selected. Defaults to `'Select…'`. */
|
|
15
|
+
placeholder?: ReactNode;
|
|
16
|
+
ref?: Ref<HTMLDivElement>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Inline-editable, fixed-option cell for the DataTable. The cell IS the select
|
|
20
|
+
* trigger, so the read view is never swapped out — opening the menu only paints
|
|
21
|
+
* the brand-orange border and drops the dropdown below (zero layout shift).
|
|
22
|
+
* When nothing is selected it renders `placeholder`.
|
|
23
|
+
*
|
|
24
|
+
* Analytics-ready: arbitrary `data-*` / `aria-*` / `id` / event props land on
|
|
25
|
+
* the trigger element, which is the real interactive node.
|
|
26
|
+
*/
|
|
27
|
+
export declare const EditableSelectCell: FC<EditableSelectCellProps>;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { Select } from "@ark-ui/react/select";
|
|
4
|
+
import { cn } from "../../../utils/cn.js";
|
|
5
|
+
import { useTestId } from "../../../utils/testId.js";
|
|
6
|
+
import { Select as index_js_Select, SelectContent, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner, createListCollection } from "../../Select/index.js";
|
|
7
|
+
import { editableCellPlaceholder, editableCellValue, editableCellVariants } from "./classes.js";
|
|
8
|
+
const EditableSelectCell = ({ value, onCommit, items, children, placeholder = 'Select…', className, ref, 'data-testid': testIdProp, ...rest })=>{
|
|
9
|
+
const testId = useTestId(void 0, testIdProp);
|
|
10
|
+
const collection = useMemo(()=>createListCollection({
|
|
11
|
+
items
|
|
12
|
+
}), [
|
|
13
|
+
items
|
|
14
|
+
]);
|
|
15
|
+
const hasValue = null != value && '' !== value;
|
|
16
|
+
return /*#__PURE__*/ jsxs(index_js_Select, {
|
|
17
|
+
className: "h-full",
|
|
18
|
+
collection: collection,
|
|
19
|
+
value: hasValue ? [
|
|
20
|
+
value
|
|
21
|
+
] : [],
|
|
22
|
+
"data-testid": testId,
|
|
23
|
+
onValueChange: (details)=>{
|
|
24
|
+
const next = details.value[0];
|
|
25
|
+
if (next && next !== value) onCommit(next);
|
|
26
|
+
},
|
|
27
|
+
children: [
|
|
28
|
+
/*#__PURE__*/ jsx(Select.Control, {
|
|
29
|
+
className: "h-full",
|
|
30
|
+
children: /*#__PURE__*/ jsx(Select.Trigger, {
|
|
31
|
+
asChild: true,
|
|
32
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
33
|
+
...rest,
|
|
34
|
+
ref: ref,
|
|
35
|
+
"data-slot": "editable-select-cell",
|
|
36
|
+
className: cn(editableCellVariants({
|
|
37
|
+
state: 'idle'
|
|
38
|
+
}), 'data-[state=open]:border-border-strong-brand data-[state=open]:bg-bg-surface-1 data-[state=open]:hover:bg-bg-surface-1', className),
|
|
39
|
+
children: hasValue ? /*#__PURE__*/ jsx("span", {
|
|
40
|
+
className: editableCellValue,
|
|
41
|
+
children: children
|
|
42
|
+
}) : /*#__PURE__*/ jsx("span", {
|
|
43
|
+
className: editableCellPlaceholder,
|
|
44
|
+
children: placeholder
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
}),
|
|
49
|
+
/*#__PURE__*/ jsx(SelectPositioner, {
|
|
50
|
+
children: /*#__PURE__*/ jsx(SelectContent, {
|
|
51
|
+
children: items.map((item)=>/*#__PURE__*/ jsxs(SelectOption, {
|
|
52
|
+
item: item,
|
|
53
|
+
children: [
|
|
54
|
+
/*#__PURE__*/ jsx(SelectOptionText, {
|
|
55
|
+
children: item.label
|
|
56
|
+
}),
|
|
57
|
+
/*#__PURE__*/ jsx(SelectOptionIndicator, {})
|
|
58
|
+
]
|
|
59
|
+
}, item.value))
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
]
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
EditableSelectCell.displayName = 'EditableSelectCell';
|
|
66
|
+
export { EditableSelectCell };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { FC, HTMLAttributes, Ref } from 'react';
|
|
2
|
+
import { type TestableProps } from '../../../utils/testId';
|
|
3
|
+
type NativeProps = Omit<HTMLAttributes<HTMLDivElement>, 'children'>;
|
|
4
|
+
export interface EditableTextCellProps extends NativeProps, TestableProps {
|
|
5
|
+
/** Current committed value. */
|
|
6
|
+
value: string;
|
|
7
|
+
/** Called with the new value on Enter / blur (only when it actually changed). */
|
|
8
|
+
onCommit: (value: string) => void;
|
|
9
|
+
ref?: Ref<HTMLDivElement>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Inline-editable text cell for the DataTable. Idle it reads as text (the whole
|
|
13
|
+
* cell highlights on hover); click / Enter / Space swaps in a borderless input
|
|
14
|
+
* in the exact same position (brand-orange border, no layout shift). Enter or
|
|
15
|
+
* blur commits, Escape reverts.
|
|
16
|
+
*
|
|
17
|
+
* Analytics-ready: arbitrary `data-*` / `aria-*` / `id` / event props (e.g.
|
|
18
|
+
* `data-analytics-id`) land on the persistent cell element, so they resolve via
|
|
19
|
+
* `closest()` whether the read view or the input is the active target.
|
|
20
|
+
*/
|
|
21
|
+
export declare const EditableTextCell: FC<EditableTextCellProps>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Pencil } from "../../../icons/index.js";
|
|
4
|
+
import { cn } from "../../../utils/cn.js";
|
|
5
|
+
import { useTestId } from "../../../utils/testId.js";
|
|
6
|
+
import { editableCellIcon, editableCellInput, editableCellValue, editableCellVariants } from "./classes.js";
|
|
7
|
+
const EditableTextCell = ({ value, onCommit, className, ref, 'data-testid': testIdProp, 'aria-label': ariaLabel, onClick, onKeyDown, ...rest })=>{
|
|
8
|
+
const testId = useTestId(void 0, testIdProp);
|
|
9
|
+
const [isEditing, setIsEditing] = useState(false);
|
|
10
|
+
const [draft, setDraft] = useState(value);
|
|
11
|
+
const start = ()=>{
|
|
12
|
+
setDraft(value);
|
|
13
|
+
setIsEditing(true);
|
|
14
|
+
};
|
|
15
|
+
const commit = ()=>{
|
|
16
|
+
setIsEditing(false);
|
|
17
|
+
if (draft !== value) onCommit(draft);
|
|
18
|
+
};
|
|
19
|
+
const cancel = ()=>{
|
|
20
|
+
setIsEditing(false);
|
|
21
|
+
setDraft(value);
|
|
22
|
+
};
|
|
23
|
+
return /*#__PURE__*/ jsx("div", {
|
|
24
|
+
...rest,
|
|
25
|
+
ref: ref,
|
|
26
|
+
"data-slot": "editable-text-cell",
|
|
27
|
+
"data-testid": testId,
|
|
28
|
+
"data-editing": isEditing || void 0,
|
|
29
|
+
className: cn(editableCellVariants({
|
|
30
|
+
state: isEditing ? 'active' : 'idle'
|
|
31
|
+
}), className),
|
|
32
|
+
role: isEditing ? void 0 : 'button',
|
|
33
|
+
tabIndex: isEditing ? void 0 : 0,
|
|
34
|
+
"aria-label": isEditing ? void 0 : ariaLabel,
|
|
35
|
+
onClick: (event)=>{
|
|
36
|
+
onClick?.(event);
|
|
37
|
+
if (!isEditing) start();
|
|
38
|
+
},
|
|
39
|
+
onKeyDown: (event)=>{
|
|
40
|
+
onKeyDown?.(event);
|
|
41
|
+
if (!isEditing && ('Enter' === event.key || ' ' === event.key)) {
|
|
42
|
+
event.preventDefault();
|
|
43
|
+
start();
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
children: isEditing ? /*#__PURE__*/ jsx("input", {
|
|
47
|
+
autoFocus: true,
|
|
48
|
+
"aria-label": ariaLabel,
|
|
49
|
+
value: draft,
|
|
50
|
+
"data-testid": testId ? `${testId}--input` : void 0,
|
|
51
|
+
onChange: (event)=>setDraft(event.currentTarget.value),
|
|
52
|
+
onFocus: (event)=>event.currentTarget.select(),
|
|
53
|
+
onBlur: commit,
|
|
54
|
+
onKeyDown: (event)=>{
|
|
55
|
+
if ('Enter' === event.key) {
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
commit();
|
|
58
|
+
} else if ('Escape' === event.key) {
|
|
59
|
+
event.preventDefault();
|
|
60
|
+
cancel();
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
className: editableCellInput
|
|
64
|
+
}) : /*#__PURE__*/ jsxs(Fragment, {
|
|
65
|
+
children: [
|
|
66
|
+
/*#__PURE__*/ jsx("span", {
|
|
67
|
+
className: editableCellValue,
|
|
68
|
+
children: value
|
|
69
|
+
}),
|
|
70
|
+
/*#__PURE__*/ jsx(Pencil, {
|
|
71
|
+
className: cn(editableCellIcon, 'opacity-0 transition-opacity group-hover/cell:opacity-100')
|
|
72
|
+
})
|
|
73
|
+
]
|
|
74
|
+
})
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
EditableTextCell.displayName = 'EditableTextCell';
|
|
78
|
+
export { EditableTextCell };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const editableCellVariants: (props?: ({
|
|
2
|
+
state?: "active" | "idle" | null | undefined;
|
|
3
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
4
|
+
/** Value slot — truncates, takes the free space, leaves room for the trailing icon. */
|
|
5
|
+
export declare const editableCellValue = "min-w-0 flex-1 truncate";
|
|
6
|
+
/** Same as the value slot but muted, for the empty-state placeholder. */
|
|
7
|
+
export declare const editableCellPlaceholder = "min-w-0 flex-1 truncate text-text-secondary";
|
|
8
|
+
/** Trailing affordance icon (pencil / chevron). */
|
|
9
|
+
export declare const editableCellIcon = "size-16 shrink-0 text-text-secondary";
|
|
10
|
+
/** Borderless in-place text editor — inherits the cell's typography and inset. */
|
|
11
|
+
export declare const editableCellInput = "min-w-0 flex-1 bg-transparent p-0 text-sm text-text-primary outline-none";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { cva } from "class-variance-authority";
|
|
2
|
+
const editableCellVariants = cva("group/cell flex h-full w-full items-center gap-8 px-16 py-8 border border-transparent text-left text-sm text-text-primary cursor-pointer outline-none transition-colors", {
|
|
3
|
+
variants: {
|
|
4
|
+
state: {
|
|
5
|
+
idle: 'hover:bg-states-primary-hover active:bg-states-primary-pressed',
|
|
6
|
+
active: 'border-border-strong-brand bg-bg-surface-1'
|
|
7
|
+
}
|
|
8
|
+
},
|
|
9
|
+
defaultVariants: {
|
|
10
|
+
state: 'idle'
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
const editableCellValue = 'min-w-0 flex-1 truncate';
|
|
14
|
+
const editableCellPlaceholder = 'min-w-0 flex-1 truncate text-text-secondary';
|
|
15
|
+
const editableCellIcon = 'size-16 shrink-0 text-text-secondary';
|
|
16
|
+
const editableCellInput = 'min-w-0 flex-1 bg-transparent p-0 text-sm text-text-primary outline-none';
|
|
17
|
+
export { editableCellIcon, editableCellInput, editableCellPlaceholder, editableCellValue, editableCellVariants };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spread onto an editable column's `meta` so `EditableTextCell` /
|
|
3
|
+
* `EditableSelectCell` can own the whole body cell:
|
|
4
|
+
*
|
|
5
|
+
* - `p-0` removes the body-cell padding (the shell re-applies its own), so the
|
|
6
|
+
* hover fill and the editing border reach the cell edges.
|
|
7
|
+
* - `h-[1px]` gives the cell a definite height. A percentage height (`h-full`
|
|
8
|
+
* on the shell) only resolves against a parent with a resolvable height; a
|
|
9
|
+
* bare table cell is `height: auto`, so the shell would sit top-aligned and
|
|
10
|
+
* leave a gap. The `1px` acts as a minimum the row grows past, and the
|
|
11
|
+
* shell's `h-full` then resolves against the real row height (the standard
|
|
12
|
+
* "fill a table-cell height" trick).
|
|
13
|
+
*
|
|
14
|
+
* Use on a NON-master column — the first/master column is pinned, cut and
|
|
15
|
+
* truncated by the Table and is not a clean host for a full-bleed editable cell.
|
|
16
|
+
*/
|
|
17
|
+
export declare const EDITABLE_CELL_COLUMN_META: {
|
|
18
|
+
readonly cellClassName: 'h-[1px] p-0';
|
|
19
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { editableCellVariants } from './classes';
|
|
2
|
+
export { EDITABLE_CELL_COLUMN_META } from './constants';
|
|
3
|
+
export { EditableSelectCell, type EditableSelectCellProps } from './EditableSelectCell';
|
|
4
|
+
export { EditableTextCell, type EditableTextCellProps } from './EditableTextCell';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { BulkBarSummary, BulkBarSummaryClear, type BulkBarSummaryClearProps, BulkBarSummaryCount, type BulkBarSummaryCountProps, type BulkBarSummaryProps, BulkBarSummarySelectAll, type BulkBarSummarySelectAllProps, BulkBarSummarySeparator, } from '../BulkBar';
|
|
2
|
+
export { EDITABLE_CELL_COLUMN_META, EditableSelectCell, type EditableSelectCellProps, EditableTextCell, type EditableTextCellProps, editableCellVariants, } from './EditableCell';
|
|
2
3
|
export { createTableColumnHelper } from './lib';
|
|
3
4
|
export type { TableColumnHelper } from './lib/createTableColumnHelper';
|
|
4
5
|
export { Table } from './Table';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { BulkBarSummary, BulkBarSummaryClear, BulkBarSummaryCount, BulkBarSummarySelectAll, BulkBarSummarySeparator } from "../BulkBar/index.js";
|
|
2
|
+
export { EDITABLE_CELL_COLUMN_META, EditableSelectCell, EditableTextCell, editableCellVariants } from "./EditableCell/index.js";
|
|
2
3
|
export { createTableColumnHelper } from "./lib/index.js";
|
|
3
4
|
export { Table } from "./Table.js";
|
|
4
5
|
export { TableActionBar, TableActionBarSelection } from "./TableActionBar/index.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -71,7 +71,7 @@ export { SplashScreen, type SplashScreenProps } from './components/SplashScreen'
|
|
|
71
71
|
export { SplitButton, type SplitButtonProps } from './components/SplitButton';
|
|
72
72
|
export { HStack, type HStackProps, Stack, type StackProps, VStack, type VStackProps, } from './components/Stack';
|
|
73
73
|
export { Switch, SwitchControl, SwitchDescription, type SwitchDescriptionProps, SwitchLabel, type SwitchLabelProps, type SwitchProps, } from './components/Switch';
|
|
74
|
-
export { createTableColumnHelper, Table, type TableAccessorColumnDef, TableActionBar, type TableCellContext, type TableColumnBase, type TableColumnDef, type TableColumnHelper, TableColumnMenu, TableColumnMenuHideItem, type TableColumnMenuHideItemProps, TableColumnMenuMoveLeftItem, type TableColumnMenuMoveLeftItemProps, TableColumnMenuMoveRightItem, type TableColumnMenuMoveRightItemProps, TableColumnMenuPinItem, type TableColumnMenuPinItemProps, type TableColumnMenuProps, TableColumnMenuSortItem, type TableColumnMenuSortItemProps, type TableColumnMeta, type TableColumnPinningState, type TableColumnSizingState, type TableDisplayColumnDef, TableEmptyState, type TableExpandedState, type TableGroupingState, type TableHandle, type TableOnChangeFn, type TableProps, type TableRow, type TableRowSelectionState, type TableScrollToRowOptions, TableSettingsMenu, type TableSortingState, TableSortTrigger, type TableSortTriggerProps, type TableUpdater, type TableVisibilityState, } from './components/Table';
|
|
74
|
+
export { createTableColumnHelper, EDITABLE_CELL_COLUMN_META, EditableSelectCell, type EditableSelectCellProps, EditableTextCell, type EditableTextCellProps, editableCellVariants, Table, type TableAccessorColumnDef, TableActionBar, type TableCellContext, type TableColumnBase, type TableColumnDef, type TableColumnHelper, TableColumnMenu, TableColumnMenuHideItem, type TableColumnMenuHideItemProps, TableColumnMenuMoveLeftItem, type TableColumnMenuMoveLeftItemProps, TableColumnMenuMoveRightItem, type TableColumnMenuMoveRightItemProps, TableColumnMenuPinItem, type TableColumnMenuPinItemProps, type TableColumnMenuProps, TableColumnMenuSortItem, type TableColumnMenuSortItemProps, type TableColumnMeta, type TableColumnPinningState, type TableColumnSizingState, type TableDisplayColumnDef, TableEmptyState, type TableExpandedState, type TableGroupingState, type TableHandle, type TableOnChangeFn, type TableProps, type TableRow, type TableRowSelectionState, type TableScrollToRowOptions, TableSettingsMenu, type TableSortingState, TableSortTrigger, type TableSortTriggerProps, type TableUpdater, type TableVisibilityState, } from './components/Table';
|
|
75
75
|
export { Tabs, TabsButton, TabsContent, TabsLineActions, TabsList, TabsSeparator, TabsTrigger, } from './components/Tabs';
|
|
76
76
|
export { Tag, TagClose, type TagProps } from './components/Tag';
|
|
77
77
|
export { Text, type TextProps } from './components/Text';
|
package/dist/index.js
CHANGED
|
@@ -60,7 +60,7 @@ export { SplashScreen } from "./components/SplashScreen/index.js";
|
|
|
60
60
|
export { SplitButton } from "./components/SplitButton/index.js";
|
|
61
61
|
export { HStack, Stack, VStack } from "./components/Stack/index.js";
|
|
62
62
|
export { Switch, SwitchControl, SwitchDescription, SwitchLabel } from "./components/Switch/index.js";
|
|
63
|
-
export { Table, TableActionBar, TableColumnMenu, TableColumnMenuHideItem, TableColumnMenuMoveLeftItem, TableColumnMenuMoveRightItem, TableColumnMenuPinItem, TableColumnMenuSortItem, TableEmptyState, TableSettingsMenu, TableSortTrigger, createTableColumnHelper } from "./components/Table/index.js";
|
|
63
|
+
export { EDITABLE_CELL_COLUMN_META, EditableSelectCell, EditableTextCell, Table, TableActionBar, TableColumnMenu, TableColumnMenuHideItem, TableColumnMenuMoveLeftItem, TableColumnMenuMoveRightItem, TableColumnMenuPinItem, TableColumnMenuSortItem, TableEmptyState, TableSettingsMenu, TableSortTrigger, createTableColumnHelper, editableCellVariants } from "./components/Table/index.js";
|
|
64
64
|
export { Tabs, TabsButton, TabsContent, TabsLineActions, TabsList, TabsSeparator, TabsTrigger } from "./components/Tabs/index.js";
|
|
65
65
|
export { Tag, TagClose } from "./components/Tag/index.js";
|
|
66
66
|
export { Text } from "./components/Text/index.js";
|