@synerise/ds-inline-edit 1.1.47 → 1.1.49
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/CHANGELOG.md +8 -0
- package/CLAUDE.md +159 -0
- package/package.json +12 -11
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.1.49](https://github.com/Synerise/synerise-design/compare/@synerise/ds-inline-edit@1.1.48...@synerise/ds-inline-edit@1.1.49) (2026-07-24)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @synerise/ds-inline-edit
|
|
9
|
+
|
|
10
|
+
## [1.1.48](https://github.com/Synerise/synerise-design/compare/@synerise/ds-inline-edit@1.1.47...@synerise/ds-inline-edit@1.1.48) (2026-07-23)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @synerise/ds-inline-edit
|
|
13
|
+
|
|
6
14
|
## [1.1.47](https://github.com/Synerise/synerise-design/compare/@synerise/ds-inline-edit@1.1.46...@synerise/ds-inline-edit@1.1.47) (2026-07-16)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @synerise/ds-inline-edit
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# InlineEdit (`@synerise/ds-inline-edit`)
|
|
2
|
+
|
|
3
|
+
> Two related components: `InlineEdit` — an autosizing text input that looks like plain text with a dashed underline on hover/focus, and an edit icon; `InlineSelect` — a read-only autosized trigger that opens a dropdown list for selection.
|
|
4
|
+
|
|
5
|
+
## Package structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
src/
|
|
9
|
+
InlineEdit.tsx — main text-input component
|
|
10
|
+
InlineEdit.types.ts — InlineEditProps, InputProps
|
|
11
|
+
InlineEdit.styles.ts — styled-components for InlineEdit
|
|
12
|
+
index.ts — public exports
|
|
13
|
+
InlineSelect/
|
|
14
|
+
InlineSelect.tsx — select-trigger component
|
|
15
|
+
InlineSelect.types.ts — InlineSelectProps
|
|
16
|
+
InlineSelect.style.ts — styled-components for InlineSelect
|
|
17
|
+
SelectDropdown/
|
|
18
|
+
SelectDropdown.tsx — virtualised dropdown menu (internal)
|
|
19
|
+
SelectDropdown.types.ts — SelectDropdownProps
|
|
20
|
+
SelectDropdown.style.ts — dropdown styled-components
|
|
21
|
+
__specs__/
|
|
22
|
+
InlineEdit.spec.tsx — Vitest tests
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Public exports
|
|
26
|
+
|
|
27
|
+
### `InlineEdit` (default export)
|
|
28
|
+
|
|
29
|
+
Functional component. Not forwardRef.
|
|
30
|
+
|
|
31
|
+
| Prop | Type | Default | Description |
|
|
32
|
+
|------|------|---------|-------------|
|
|
33
|
+
| `input` | `InputProps` | — | **Required.** Value, event handlers, and native input attributes |
|
|
34
|
+
| `size` | `'large' \| 'normal' \| 'small'` | `'normal'` | Controls font size via `@synerise/ds-typography` macros |
|
|
35
|
+
| `disabled` | `boolean` | `undefined` | Disables input and hides the icon via `pointer-events: none` |
|
|
36
|
+
| `error` | `boolean` | `undefined` | Switches underline/text colour to `red-600` |
|
|
37
|
+
| `hideIcon` | `boolean` | `undefined` | Hides the edit icon entirely |
|
|
38
|
+
| `customIcon` | `ReactNode` | `undefined` | Replaces the default `EditS` icon |
|
|
39
|
+
| `tooltipTitle` | `string` | `undefined` | Tooltip shown on hover over the icon |
|
|
40
|
+
| `autoFocus` | `boolean` | `undefined` | Focuses the input after mount via `useEffect` |
|
|
41
|
+
| `className` | `string` | `undefined` | Appended to `.ds-inline-edit` |
|
|
42
|
+
| `style` | `CSSProperties` | `undefined` | Applied to the root container |
|
|
43
|
+
|
|
44
|
+
### `InputProps`
|
|
45
|
+
|
|
46
|
+
Passed as the `input` prop to both `InlineEdit` and `InlineSelect`.
|
|
47
|
+
|
|
48
|
+
| Prop | Type | Required | Description |
|
|
49
|
+
|------|------|----------|-------------|
|
|
50
|
+
| `value` | `string \| number` | yes | Controlled value |
|
|
51
|
+
| `onChange` | `(event: ChangeEvent<HTMLInputElement>) => void` | yes | Change handler (not called in `InlineSelect` — use `onValueChange`) |
|
|
52
|
+
| `name` | `string` | no | Used to derive the input `id` via `toCamelCase(name)` |
|
|
53
|
+
| `disabled` | `boolean` | no | Native input disabled |
|
|
54
|
+
| `onBlur` | `FocusEventHandler<HTMLInputElement>` | no | Called on blur |
|
|
55
|
+
| `onEnterPress` | `KeyboardEventHandler<HTMLInputElement>` | no | Called on Enter key; also triggers `blur()` |
|
|
56
|
+
| `placeholder` | `string` | no | Placeholder text |
|
|
57
|
+
| `maxLength` | `number` | no | Maximum character count |
|
|
58
|
+
| `readOnly` | `boolean` | no | Native input readOnly |
|
|
59
|
+
| `autoComplete` | `InputHTMLAttributes<HTMLInputElement>['autoComplete']` | no | Native autocomplete attribute |
|
|
60
|
+
|
|
61
|
+
### `InlineSelect`
|
|
62
|
+
|
|
63
|
+
Generic component: `InlineSelect<ItemType extends ListItemProps>`. Functional, not forwardRef.
|
|
64
|
+
|
|
65
|
+
| Prop | Type | Default | Description |
|
|
66
|
+
|------|------|---------|-------------|
|
|
67
|
+
| `dataSource` | `ItemType[]` | — | **Required.** Array of `ListItemProps` items to show in dropdown |
|
|
68
|
+
| `input` | `Partial<Omit<InputProps, 'placeholder'>>` | — | **Required.** `value` syncs the displayed text; `onChange` is replaced with `NOOP` — use `onValueChange` instead |
|
|
69
|
+
| `onValueChange` | `(item: ItemType) => void` | `undefined` | Called when a dropdown item is selected |
|
|
70
|
+
| `initialValue` | `string` | `undefined` | Initial displayed text (overrides `placeholder`) |
|
|
71
|
+
| `placeholder` | `string` | `undefined` | Text shown when no value is selected |
|
|
72
|
+
| `size` | `'normal' \| 'small'` | `'normal'` | Font size via typography macros (no `'large'` unlike `InlineEdit`) |
|
|
73
|
+
| `expanded` | `boolean` | `undefined` | Sets initial open state of the dropdown |
|
|
74
|
+
| `disabled` | `boolean` | `undefined` | Disables interaction; adds 0.4 opacity |
|
|
75
|
+
| `error` | `boolean` | `undefined` | Switches underline/text colour to `red-600` |
|
|
76
|
+
| `hideIcon` | `boolean` | `undefined` | Hides the `AngleDownS` chevron icon |
|
|
77
|
+
| `dropdownProps` | `Partial<Omit<DropdownSharedProps, 'open' \| 'onOpenChange' \| 'children' \| 'overlay' \| 'disabled'>>` | `{}` | Extra props forwarded to `@synerise/ds-dropdown` |
|
|
78
|
+
| `dropdownOverlayStyle` | `CSSProperties` | `{}` | Style applied to the dropdown overlay wrapper |
|
|
79
|
+
| `inputStyle` | `CSSProperties` | `undefined` | Style applied to the inner `<input>` element |
|
|
80
|
+
| `autoFocus` | `boolean` | `undefined` | Focuses the input after mount |
|
|
81
|
+
| `className` | `string` | `undefined` | Appended to `.ds-inline-edit` |
|
|
82
|
+
| `style` | `CSSProperties` | `undefined` | Applied to root container |
|
|
83
|
+
|
|
84
|
+
> **`tooltipTitle`** is declared in `InlineSelectProps` but is **not used** in `InlineSelect.tsx`.
|
|
85
|
+
|
|
86
|
+
### Types exported
|
|
87
|
+
|
|
88
|
+
| Type | Description |
|
|
89
|
+
|------|-------------|
|
|
90
|
+
| `InlineEditProps` | Props for `InlineEdit` |
|
|
91
|
+
| `InputProps` | Props for the `input` object passed to both components |
|
|
92
|
+
| `InlineSelectProps<ItemType>` | Props for `InlineSelect` |
|
|
93
|
+
|
|
94
|
+
## Usage patterns
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
import InlineEdit, { InlineSelect } from '@synerise/ds-inline-edit';
|
|
98
|
+
|
|
99
|
+
// InlineEdit
|
|
100
|
+
<InlineEdit
|
|
101
|
+
input={{
|
|
102
|
+
name: 'title',
|
|
103
|
+
value: title,
|
|
104
|
+
placeholder: 'Enter title',
|
|
105
|
+
onChange: (e) => setTitle(e.target.value),
|
|
106
|
+
onEnterPress: () => handleSave(),
|
|
107
|
+
}}
|
|
108
|
+
size="normal"
|
|
109
|
+
tooltipTitle="Edit"
|
|
110
|
+
/>
|
|
111
|
+
|
|
112
|
+
// InlineSelect
|
|
113
|
+
<InlineSelect
|
|
114
|
+
dataSource={[
|
|
115
|
+
{ text: 'Option A' },
|
|
116
|
+
{ text: 'Option B' },
|
|
117
|
+
]}
|
|
118
|
+
input={{ value: selectedText }}
|
|
119
|
+
onValueChange={(item) => setSelected(item.text as string)}
|
|
120
|
+
placeholder="Select.."
|
|
121
|
+
/>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Styling
|
|
125
|
+
|
|
126
|
+
**`InlineEdit`** styles in `InlineEdit.styles.ts`:
|
|
127
|
+
- No visible border; uses a CSS dashed `background-image` gradient as an underline
|
|
128
|
+
- On hover/focus: `grey-400` dots underline (or `red-600` if `error`)
|
|
129
|
+
- On focus: `blue-600` dots underline (or `red-600` if `error`)
|
|
130
|
+
- Font size driven by `size` prop: `large` → `macro.h600`, `normal` → `macro.h400`, `small` → `macro.small`
|
|
131
|
+
- Disabled: `pointer-events: none` + icon hidden via `display: none`
|
|
132
|
+
|
|
133
|
+
**`InlineSelect`** styles in `InlineSelect.style.ts`:
|
|
134
|
+
- Text colour rendered via CSS `text-shadow` trick: input `color: transparent`, shadow is `blue-600`/`red-600`
|
|
135
|
+
- Icon animates 180° rotation when dropdown is open
|
|
136
|
+
- Disabled: 0.4 opacity + `pointer-events: none`
|
|
137
|
+
- Has a `// todo: set type` comment next to font size for `normal`/`small` sizes
|
|
138
|
+
|
|
139
|
+
## Key dependencies
|
|
140
|
+
|
|
141
|
+
- `@synerise/ds-input` — `AutosizeInput` wrapper that grows the input with content
|
|
142
|
+
- `@synerise/ds-icon` — `EditS` (InlineEdit) and `AngleDownS` (InlineSelect) icons
|
|
143
|
+
- `@synerise/ds-dropdown` — dropdown trigger wrapper for `InlineSelect`
|
|
144
|
+
- `@synerise/ds-search` — `SearchItems` for virtualised list rendering in `SelectDropdown`
|
|
145
|
+
- `@synerise/ds-list-item` — `ListItemProps` item type constraint
|
|
146
|
+
- `@synerise/ds-tooltip` — wraps the edit icon in `InlineEdit`
|
|
147
|
+
- `@synerise/ds-typography` — `macro` font-size helpers
|
|
148
|
+
- `@synerise/ds-utils` — `toCamelCase` (for input `id`), `NOOP`
|
|
149
|
+
|
|
150
|
+
## Implementation notes
|
|
151
|
+
|
|
152
|
+
- **`input.onChange` is NOOP in `InlineSelect`**: The inner `<input>` gets `onChange={NOOP}`. Consumer `onChange` from `input` is destructured but discarded. Only `onValueChange` is called on item selection.
|
|
153
|
+
- **Input `id` fallback**: When `input.name` is not provided, both components use the literal string `'id'` as the input element's `id`. Multiple instances without `name` will all have `id="id"` — potential accessibility/form collision.
|
|
154
|
+
- **`customIcon` uses deprecated `component` prop**: `InlineEdit` passes `customIcon` to `<Icon component={customIcon || <EditS />} />` — the deprecated `component` prop pattern.
|
|
155
|
+
- **`scrolled` state**: `focused` state in `InlineEdit` is named misleadingly. It is set to `false` on focus (to enable `text-overflow: ellipsis`) and `true` on blur (switching to `text-overflow: initial` so text isn't clipped when scrolled). On blur, `inputRef.current.scrollTo({ left: 0 })` resets scroll.
|
|
156
|
+
- **`InlineSelect` `size` is narrower**: Only `'normal' | 'small'` — no `'large'` (unlike `InlineEdit` which supports `'large'`).
|
|
157
|
+
- **`tooltipTitle` in `InlineSelect`**: Declared in `InlineSelectProps` but never rendered — passing it has no effect.
|
|
158
|
+
- **`SelectDropdown`** is internal (not exported). Its `Props` alias is marked `@deprecated` in `SelectDropdown.types.ts` but the file is not in the public exports.
|
|
159
|
+
- **Uses Vitest** for testing.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synerise/ds-inline-edit",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.49",
|
|
4
4
|
"description": "InlineEdit UI Component for the Synerise Design System",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"repository": "Synerise/synerise-design",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"files": [
|
|
18
18
|
"/dist",
|
|
19
19
|
"CHANGELOG.md",
|
|
20
|
+
"CLAUDE.md",
|
|
20
21
|
"README.md",
|
|
21
22
|
"package.json",
|
|
22
23
|
"LICENSE.md"
|
|
@@ -41,15 +42,15 @@
|
|
|
41
42
|
],
|
|
42
43
|
"types": "dist/index.d.ts",
|
|
43
44
|
"dependencies": {
|
|
44
|
-
"@synerise/ds-dropdown": "^1.3.
|
|
45
|
-
"@synerise/ds-icon": "^1.18.
|
|
46
|
-
"@synerise/ds-input": "^1.7.
|
|
47
|
-
"@synerise/ds-list-item": "^1.6.
|
|
48
|
-
"@synerise/ds-scrollbar": "^1.5.
|
|
49
|
-
"@synerise/ds-search": "^1.5.
|
|
50
|
-
"@synerise/ds-tooltip": "^1.5.
|
|
51
|
-
"@synerise/ds-typography": "^1.1.
|
|
52
|
-
"@synerise/ds-utils": "^1.10.
|
|
45
|
+
"@synerise/ds-dropdown": "^1.3.21",
|
|
46
|
+
"@synerise/ds-icon": "^1.18.5",
|
|
47
|
+
"@synerise/ds-input": "^1.7.14",
|
|
48
|
+
"@synerise/ds-list-item": "^1.6.2",
|
|
49
|
+
"@synerise/ds-scrollbar": "^1.5.2",
|
|
50
|
+
"@synerise/ds-search": "^1.5.34",
|
|
51
|
+
"@synerise/ds-tooltip": "^1.5.4",
|
|
52
|
+
"@synerise/ds-typography": "^1.1.27",
|
|
53
|
+
"@synerise/ds-utils": "^1.10.2"
|
|
53
54
|
},
|
|
54
55
|
"peerDependencies": {
|
|
55
56
|
"@synerise/ds-core": "*",
|
|
@@ -57,5 +58,5 @@
|
|
|
57
58
|
"styled-components": "^5.3.3",
|
|
58
59
|
"vitest": "4"
|
|
59
60
|
},
|
|
60
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "018414e0d7ffd102a07f8aa35fa2e2d3d4ed19e2"
|
|
61
62
|
}
|