cursedbelt 5.113.1 → 5.114.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/react/components/InlineEditableText.d.ts +11 -1
- package/dist/react/components/InlineEditableText.d.ts.map +1 -1
- package/dist/react/components/InlineEditableText.js +5 -4
- package/dist/react/components/InlineEditableText.js.map +1 -1
- package/package.json +1 -1
- package/src/react/components/InlineEditableText.spec.tsx +25 -0
- package/src/react/components/InlineEditableText.tsx +16 -4
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
1
2
|
export interface InlineEditableTextProps {
|
|
2
3
|
value: string;
|
|
3
4
|
/** Called with the trimmed next value, only when it actually changed. */
|
|
@@ -35,6 +36,15 @@ export interface InlineEditableTextProps {
|
|
|
35
36
|
* would otherwise replace everything they wrote.
|
|
36
37
|
*/
|
|
37
38
|
caret?: 'select-all' | 'end';
|
|
39
|
+
/**
|
|
40
|
+
* How the value reads when it is NOT being edited — the click-to-edit display and the
|
|
41
|
+
* read-only text alike; the editor still edits the raw string. For text with structure
|
|
42
|
+
* the string only encodes (a read table's tab-separated rows drawn as a grid). The
|
|
43
|
+
* editable display is a `<button>`, so this returns phrasing content: spans, styled
|
|
44
|
+
* into whatever shape the text needs. Never called for an empty value — the
|
|
45
|
+
* placeholder shows then.
|
|
46
|
+
*/
|
|
47
|
+
display?: (value: string) => ReactNode;
|
|
38
48
|
/** The editor's character ceiling (default 10,000) — the server's limit, so the editor stops where a save would be refused. */
|
|
39
49
|
maxLength?: number;
|
|
40
50
|
ariaLabel?: string;
|
|
@@ -47,5 +57,5 @@ export interface InlineEditableTextProps {
|
|
|
47
57
|
* selects its text on mount so typing replaces (and the cursor is never stranded
|
|
48
58
|
* at position 0) — or, with `caret='end'`, puts the caret after the text.
|
|
49
59
|
*/
|
|
50
|
-
export declare function InlineEditableText({ value, onChange, canEdit, multiline, placeholder, className, inputClassName, trigger, wrap, caret, maxLength, ariaLabel, ...rest }: InlineEditableTextProps): import("react").JSX.Element | null;
|
|
60
|
+
export declare function InlineEditableText({ value, onChange, canEdit, multiline, placeholder, className, inputClassName, trigger, wrap, caret, maxLength, ariaLabel, display, ...rest }: InlineEditableTextProps): import("react").JSX.Element | null;
|
|
51
61
|
//# sourceMappingURL=InlineEditableText.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InlineEditableText.d.ts","sourceRoot":"","sources":["../../../src/react/components/InlineEditableText.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"InlineEditableText.d.ts","sourceRoot":"","sources":["../../../src/react/components/InlineEditableText.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAyB,MAAM,OAAO,CAAC;AAS9D,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;gEAC4D;IAC5D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;gEAC4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;sDAGkD;IAClD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,YAAY,GAAG,KAAK,CAAC;IAC7B;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC;IACvC,+HAA+H;IAC/H,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,QAAQ,EACR,OAAc,EACd,SAAiB,EACjB,WAAyB,EACzB,SAAS,EACT,cAAc,EACd,OAAgB,EAChB,IAAW,EACX,KAAoB,EACpB,SAAkB,EAClB,SAAS,EACT,OAAO,EACP,GAAG,IAAI,EACR,EAAE,uBAAuB,sCAkJzB"}
|
|
@@ -16,7 +16,7 @@ import { RAW_BUTTON } from '../lib/cn.js';
|
|
|
16
16
|
* selects its text on mount so typing replaces (and the cursor is never stranded
|
|
17
17
|
* at position 0) — or, with `caret='end'`, puts the caret after the text.
|
|
18
18
|
*/
|
|
19
|
-
export function InlineEditableText({ value, onChange, canEdit = true, multiline = false, placeholder = 'Add text…', className, inputClassName, trigger = 'text', wrap = true, caret = 'select-all', maxLength = 10_000, ariaLabel, ...rest }) {
|
|
19
|
+
export function InlineEditableText({ value, onChange, canEdit = true, multiline = false, placeholder = 'Add text…', className, inputClassName, trigger = 'text', wrap = true, caret = 'select-all', maxLength = 10_000, ariaLabel, display, ...rest }) {
|
|
20
20
|
const [editing, setEditing] = useState(false);
|
|
21
21
|
const [draft, setDraft] = useState(value);
|
|
22
22
|
const begin = () => {
|
|
@@ -74,13 +74,14 @@ export function InlineEditableText({ value, onChange, canEdit = true, multiline
|
|
|
74
74
|
// Read-only with no value → render nothing.
|
|
75
75
|
if (!canEdit && !value)
|
|
76
76
|
return null;
|
|
77
|
+
const shown = value && display ? display(value) : value || placeholder;
|
|
77
78
|
// Read-only: plain text.
|
|
78
79
|
if (!canEdit)
|
|
79
|
-
return _jsx("span", { ...rest, className: className, children:
|
|
80
|
+
return _jsx("span", { ...rest, className: className, children: shown });
|
|
80
81
|
// Icon trigger: text is inert (rows where clicking the text means open/select);
|
|
81
82
|
// the pencil is the explicit edit affordance.
|
|
82
83
|
if (trigger === 'icon') {
|
|
83
|
-
return (_jsxs("span", { ...rest, className: 'inline-flex min-w-0 items-center gap-1', children: [_jsx("span", { className: cn('truncate', !value && 'italic text-muted-foreground', className), children:
|
|
84
|
+
return (_jsxs("span", { ...rest, className: 'inline-flex min-w-0 items-center gap-1', children: [_jsx("span", { className: cn('truncate', !value && 'italic text-muted-foreground', className), children: shown }), _jsx(IconButton, { size: 'sm', label: ariaLabel ? `Edit ${ariaLabel}` : 'Edit', onClick: begin, children: _jsx(Pencil, {}) })] }));
|
|
84
85
|
}
|
|
85
86
|
// Editable display: a real <button> so Enter/Space activation + focus come free,
|
|
86
87
|
// styled to read as inline text.
|
|
@@ -103,6 +104,6 @@ export function InlineEditableText({ value, onChange, canEdit = true, multiline
|
|
|
103
104
|
// measuring gate (and any tool that reasons about layout) still sees 24px.
|
|
104
105
|
// `DESIGN.md` §5's footprint is the floor and UX_STANDARDS §0 records that it
|
|
105
106
|
// wins over the band — so the box grows too, and the band stays as the extra.
|
|
106
|
-
TAP_TARGET_HEIGHT, 'pointer-coarse:before:absolute pointer-coarse:before:top-[calc(var(--hit-slop-y)*-1)] pointer-coarse:before:bottom-[calc(var(--hit-slop-y)*-1)] pointer-coarse:before:-left-1 pointer-coarse:before:-right-1 pointer-coarse:before:content-[""]', wrap ? 'whitespace-pre-wrap break-words' : 'block w-full truncate', !value && 'italic text-muted-foreground', className), children:
|
|
107
|
+
TAP_TARGET_HEIGHT, 'pointer-coarse:before:absolute pointer-coarse:before:top-[calc(var(--hit-slop-y)*-1)] pointer-coarse:before:bottom-[calc(var(--hit-slop-y)*-1)] pointer-coarse:before:-left-1 pointer-coarse:before:-right-1 pointer-coarse:before:content-[""]', wrap ? 'whitespace-pre-wrap break-words' : 'block w-full truncate', !value && 'italic text-muted-foreground', className), children: shown }) }));
|
|
107
108
|
}
|
|
108
109
|
//# sourceMappingURL=InlineEditableText.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InlineEditableText.js","sourceRoot":"","sources":["../../../src/react/components/InlineEditableText.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,
|
|
1
|
+
{"version":3,"file":"InlineEditableText.js","sourceRoot":"","sources":["../../../src/react/components/InlineEditableText.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cursedbelt",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.114.0",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The React design system of the cursedbelt split — components, styles, theme. cursedbelt-core below it; server tier in cursedbelt-server.",
|
|
@@ -83,4 +83,29 @@ describe('InlineEditableText', () => {
|
|
|
83
83
|
expect(queryByRole('button')).toBeNull();
|
|
84
84
|
expect(queryByRole('textbox')).toBeNull();
|
|
85
85
|
});
|
|
86
|
+
|
|
87
|
+
test('display draws the value when not editing; the editor still edits the raw text', () => {
|
|
88
|
+
const table = 'Size\tTemp\nSmall\t220 C';
|
|
89
|
+
const grid = (v: string) => <span data-testid='grid'>{v.split('\n').length} rows</span>;
|
|
90
|
+
const onChange = mock(() => {});
|
|
91
|
+
const { getByRole, getByTestId, queryByTestId } = render(
|
|
92
|
+
<InlineEditableText multiline value={table} display={grid} onChange={onChange} />,
|
|
93
|
+
);
|
|
94
|
+
expect(getByTestId('grid').textContent).toBe('2 rows');
|
|
95
|
+
fireEvent.click(getByRole('button'));
|
|
96
|
+
expect(queryByTestId('grid')).toBeNull();
|
|
97
|
+
expect((getByRole('textbox') as HTMLTextAreaElement).value).toBe(table);
|
|
98
|
+
cleanup();
|
|
99
|
+
const locked = render(<InlineEditableText canEdit={false} value={table} display={grid} onChange={() => {}} />);
|
|
100
|
+
expect(locked.getByTestId('grid').textContent).toBe('2 rows');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('display is never called for an empty value — the placeholder shows', () => {
|
|
104
|
+
const display = mock((v: string) => <span>{v}</span>);
|
|
105
|
+
const { getByRole } = render(
|
|
106
|
+
<InlineEditableText value='' placeholder='Type it' display={display} onChange={() => {}} />,
|
|
107
|
+
);
|
|
108
|
+
expect(getByRole('button').textContent).toBe('Type it');
|
|
109
|
+
expect(display).not.toHaveBeenCalled();
|
|
110
|
+
});
|
|
86
111
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Pencil } from 'lucide-react';
|
|
2
|
-
import { useCallback, useState } from 'react';
|
|
2
|
+
import { type ReactNode, useCallback, useState } from 'react';
|
|
3
3
|
import { cn } from '../lib/cn.js';
|
|
4
4
|
import { AutoGrowTextarea } from './AutoGrowTextarea.js';
|
|
5
5
|
import { IconButton } from './IconButton.js';
|
|
@@ -45,6 +45,15 @@ export interface InlineEditableTextProps {
|
|
|
45
45
|
* would otherwise replace everything they wrote.
|
|
46
46
|
*/
|
|
47
47
|
caret?: 'select-all' | 'end';
|
|
48
|
+
/**
|
|
49
|
+
* How the value reads when it is NOT being edited — the click-to-edit display and the
|
|
50
|
+
* read-only text alike; the editor still edits the raw string. For text with structure
|
|
51
|
+
* the string only encodes (a read table's tab-separated rows drawn as a grid). The
|
|
52
|
+
* editable display is a `<button>`, so this returns phrasing content: spans, styled
|
|
53
|
+
* into whatever shape the text needs. Never called for an empty value — the
|
|
54
|
+
* placeholder shows then.
|
|
55
|
+
*/
|
|
56
|
+
display?: (value: string) => ReactNode;
|
|
48
57
|
/** The editor's character ceiling (default 10,000) — the server's limit, so the editor stops where a save would be refused. */
|
|
49
58
|
maxLength?: number;
|
|
50
59
|
ariaLabel?: string;
|
|
@@ -71,6 +80,7 @@ export function InlineEditableText({
|
|
|
71
80
|
caret = 'select-all',
|
|
72
81
|
maxLength = 10_000,
|
|
73
82
|
ariaLabel,
|
|
83
|
+
display,
|
|
74
84
|
...rest
|
|
75
85
|
}: InlineEditableTextProps) {
|
|
76
86
|
const [editing, setEditing] = useState(false);
|
|
@@ -161,8 +171,10 @@ export function InlineEditableText({
|
|
|
161
171
|
// Read-only with no value → render nothing.
|
|
162
172
|
if (!canEdit && !value) return null;
|
|
163
173
|
|
|
174
|
+
const shown = value && display ? display(value) : value || placeholder;
|
|
175
|
+
|
|
164
176
|
// Read-only: plain text.
|
|
165
|
-
if (!canEdit) return <span {...rest} className={className}>{
|
|
177
|
+
if (!canEdit) return <span {...rest} className={className}>{shown}</span>;
|
|
166
178
|
|
|
167
179
|
// Icon trigger: text is inert (rows where clicking the text means open/select);
|
|
168
180
|
// the pencil is the explicit edit affordance.
|
|
@@ -170,7 +182,7 @@ export function InlineEditableText({
|
|
|
170
182
|
return (
|
|
171
183
|
<span {...rest} className='inline-flex min-w-0 items-center gap-1'>
|
|
172
184
|
<span className={cn('truncate', !value && 'italic text-muted-foreground', className)}>
|
|
173
|
-
{
|
|
185
|
+
{shown}
|
|
174
186
|
</span>
|
|
175
187
|
<IconButton size='sm' label={ariaLabel ? `Edit ${ariaLabel}` : 'Edit'} onClick={begin}>
|
|
176
188
|
<Pencil />
|
|
@@ -212,7 +224,7 @@ export function InlineEditableText({
|
|
|
212
224
|
className,
|
|
213
225
|
)}
|
|
214
226
|
>
|
|
215
|
-
{
|
|
227
|
+
{shown}
|
|
216
228
|
</button>
|
|
217
229
|
</Tooltip>
|
|
218
230
|
);
|