@synerise/ds-subtle-form 1.2.7 → 1.2.8
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 +4 -0
- package/CLAUDE.md +172 -0
- package/package.json +10 -9
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
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.2.8](https://github.com/Synerise/synerise-design/compare/@synerise/ds-subtle-form@1.2.7...@synerise/ds-subtle-form@1.2.8) (2026-07-23)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @synerise/ds-subtle-form
|
|
9
|
+
|
|
6
10
|
## [1.2.7](https://github.com/Synerise/synerise-design/compare/@synerise/ds-subtle-form@1.2.6...@synerise/ds-subtle-form@1.2.7) (2026-07-16)
|
|
7
11
|
|
|
8
12
|
**Note:** Version bump only for package @synerise/ds-subtle-form
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# SubtleForm (`@synerise/ds-subtle-form`)
|
|
2
|
+
|
|
3
|
+
> A compound form component providing 5 inline-edit sub-components (TextArea, Input, Select, DatePicker, Field) that toggle between a static display state and an active edit state on click/hover.
|
|
4
|
+
|
|
5
|
+
## Package structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
src/
|
|
9
|
+
SubtleForm.tsx — namespace component (returns null); attaches sub-components as static properties
|
|
10
|
+
SubtleForm.types.ts — SubtleFieldProps (shared base type)
|
|
11
|
+
SubtleForm.styles.ts — shared styled components: Inactive, MainContent, Suffix, Container, Subtle, SubtleFormField, ValueArea; animation keyframes
|
|
12
|
+
index.ts — default export only (no type re-exports)
|
|
13
|
+
Elements/
|
|
14
|
+
TextArea/TextArea.tsx — textarea with dynamic row height calculation
|
|
15
|
+
TextArea/TextArea.types.ts — SubtleTextAreaProps, TextareaAutosize
|
|
16
|
+
Input/Input.tsx — single-line text input
|
|
17
|
+
Input/Input.types.ts — SubtleInputProps
|
|
18
|
+
Select/Select.tsx — Ant Design select dropdown
|
|
19
|
+
Select/Select.types.ts — SubtleSelectProps
|
|
20
|
+
Select/Select.styles.ts — SelectContainer (handles active margin offset)
|
|
21
|
+
DatePicker/DatePicker.tsx — date picker with formatted value display and mask placeholder
|
|
22
|
+
DatePicker/DatePicker.types.ts — SubtleDatePickerProps
|
|
23
|
+
DatePicker/DatePicker.styles.ts — SelectContainer, MaskedDatePlaceholder
|
|
24
|
+
DatePicker/utils.ts — getFormattingString, replaceLettersWithUnderscore
|
|
25
|
+
Field/Field.tsx — generic field: renders activeElement() / inactiveElement(); uses useOnClickOutside
|
|
26
|
+
__specs__/
|
|
27
|
+
TextArea.spec.tsx — Vitest tests (TextArea only)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Public exports
|
|
31
|
+
|
|
32
|
+
### `SubtleForm` (default export)
|
|
33
|
+
|
|
34
|
+
The component itself returns `null`. It is used only as a namespace:
|
|
35
|
+
|
|
36
|
+
- `SubtleForm.TextArea`
|
|
37
|
+
- `SubtleForm.Input`
|
|
38
|
+
- `SubtleForm.Select`
|
|
39
|
+
- `SubtleForm.DatePicker`
|
|
40
|
+
- `SubtleForm.Field`
|
|
41
|
+
|
|
42
|
+
No type exports from `index.ts`.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
### Shared `SubtleFieldProps` (base for all sub-components)
|
|
47
|
+
|
|
48
|
+
| Prop | Type | Description |
|
|
49
|
+
|------|------|-------------|
|
|
50
|
+
| `label` | `FormFieldCommonProps['label']` | Label above the field |
|
|
51
|
+
| `labelTooltip` | `FormFieldCommonProps['tooltip']` | Tooltip on the label |
|
|
52
|
+
| `errorText` | `FormFieldCommonProps['errorText']` | Error message; forces active/edit state |
|
|
53
|
+
| `disabled` | `boolean` | Disables interactions, 0.5 opacity |
|
|
54
|
+
| `suffix` | `ReactNode` | Custom suffix icon in inactive state (replaces default edit icon) |
|
|
55
|
+
| `suffixTooltip` | `ReactNode` | Tooltip on the suffix icon |
|
|
56
|
+
| `active` | `boolean` | Controlled active state (`Field` only) |
|
|
57
|
+
| `activeElement` | `() => ReactElement` | Render function for edit state (`Field` only) |
|
|
58
|
+
| `inactiveElement` | `() => ReactElement` | Render function for display state (`Field` only) |
|
|
59
|
+
| `mask` | `string` | Mask string shown below inactive content (`Field` only) |
|
|
60
|
+
| `maskVisible` | `boolean` | Whether to show the mask (`Field` only) |
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### `SubtleForm.TextArea`
|
|
65
|
+
|
|
66
|
+
| Prop | Type | Default | Description |
|
|
67
|
+
|------|------|---------|-------------|
|
|
68
|
+
| `value` | `string` | — | Current value |
|
|
69
|
+
| `onChange` | `(value: string) => void` | — | Called on input change |
|
|
70
|
+
| `placeholder` | `string` | — | Shown when no value |
|
|
71
|
+
| `minRows` | `number` | `1` | Minimum textarea rows |
|
|
72
|
+
| `maxRows` | `number` | — | Maximum textarea rows (clamps auto-height) |
|
|
73
|
+
| `error` | `boolean` | — | Error state; forces edit mode |
|
|
74
|
+
| `textAreaProps` | `TextAreaProps` | — | Props forwarded to `@synerise/ds-input` TextArea |
|
|
75
|
+
| + all `SubtleFieldProps` | | | |
|
|
76
|
+
|
|
77
|
+
### `SubtleForm.Input`
|
|
78
|
+
|
|
79
|
+
| Prop | Type | Default | Description |
|
|
80
|
+
|------|------|---------|-------------|
|
|
81
|
+
| `value` | `string` | — | Current value |
|
|
82
|
+
| `onChange` | `(value: string) => void` | — | Called on input change |
|
|
83
|
+
| `placeholder` | `string` | — | Shown when no value |
|
|
84
|
+
| `error` | `boolean` | — | Error state; forces edit mode |
|
|
85
|
+
| `inputProps` | `InputProps` | — (**required**) | Props forwarded to Ant Design `Input` |
|
|
86
|
+
| + all `SubtleFieldProps` | | | |
|
|
87
|
+
|
|
88
|
+
### `SubtleForm.Select`
|
|
89
|
+
|
|
90
|
+
Extends `SubtleFieldProps` + `@synerise/ds-select` props. Additional:
|
|
91
|
+
|
|
92
|
+
| Prop | Type | Description |
|
|
93
|
+
|------|------|-------------|
|
|
94
|
+
| `placeholder` | `string` | Shown when no value |
|
|
95
|
+
| `dropdownAlign` | `object` | Ant Design `dropdownAlign`; defaults to `{}` (offset `[0, 8]` applied) |
|
|
96
|
+
| `children` | `ReactNode` | `Select.Option` children |
|
|
97
|
+
|
|
98
|
+
### `SubtleForm.DatePicker`
|
|
99
|
+
|
|
100
|
+
Extends `SubtleFieldProps` + `@synerise/ds-date-picker` props. Additional:
|
|
101
|
+
|
|
102
|
+
| Prop | Type | Description |
|
|
103
|
+
|------|------|-------------|
|
|
104
|
+
| `value` | `Date` | Selected date |
|
|
105
|
+
| `onApply` | `(date: Date) => void` | Called when date is confirmed; also deactivates the field |
|
|
106
|
+
| `onClear` | `() => void` | Called on clear; also deactivates |
|
|
107
|
+
| `format` | `string` | Date format string (default: `'dd-MM-yyyy'`, or `'dd-MM-yyyy, HH:mm'` when `showTime`) |
|
|
108
|
+
| `placeholder` | `string` | Shown when no value |
|
|
109
|
+
| `activeProp` | `boolean` | External control of active state |
|
|
110
|
+
|
|
111
|
+
### `SubtleForm.Field`
|
|
112
|
+
|
|
113
|
+
Generic field using `SubtleFieldProps` props only (no additional props). Uses `activeElement()` and `inactiveElement()` callbacks to render edit/display states.
|
|
114
|
+
|
|
115
|
+
## Usage patterns
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
import SubtleForm from '@synerise/ds-subtle-form';
|
|
119
|
+
|
|
120
|
+
// TextArea
|
|
121
|
+
const [value, setValue] = React.useState('');
|
|
122
|
+
<SubtleForm.TextArea
|
|
123
|
+
value={value}
|
|
124
|
+
onChange={setValue}
|
|
125
|
+
placeholder="Description"
|
|
126
|
+
label="Label"
|
|
127
|
+
labelTooltip="Tooltip"
|
|
128
|
+
suffixTooltip="Edit"
|
|
129
|
+
minRows={3}
|
|
130
|
+
/>
|
|
131
|
+
|
|
132
|
+
// Input
|
|
133
|
+
<SubtleForm.Input
|
|
134
|
+
value={name}
|
|
135
|
+
onChange={setName}
|
|
136
|
+
placeholder="Name"
|
|
137
|
+
label="Name"
|
|
138
|
+
inputProps={{}}
|
|
139
|
+
/>
|
|
140
|
+
|
|
141
|
+
// Custom Field
|
|
142
|
+
<SubtleForm.Field
|
|
143
|
+
active={active}
|
|
144
|
+
activeElement={() => <InputNumber value={val} onBlur={() => setActive(false)} />}
|
|
145
|
+
inactiveElement={() => <>{val ?? 'placeholder'}</>}
|
|
146
|
+
label="Number"
|
|
147
|
+
/>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Styling
|
|
151
|
+
|
|
152
|
+
`SubtleForm.styles.ts`. Key pattern: `Inactive` div has `padding: 7px 40px 7px 0` at rest, animates to `padding: 7px 28px 7px 12px` on hover. The `Suffix` icon uses `opacity: 0` → `1` transition on hover. A `blurAnimation` keyframe plays once after blur to reverse the padding. `SubtleFormField` (extends `FormField`) uses `gap: 10px` when active, `8px` at rest.
|
|
153
|
+
|
|
154
|
+
## Key dependencies
|
|
155
|
+
|
|
156
|
+
- `@synerise/ds-input` — `Input` and `TextArea` for edit state
|
|
157
|
+
- `@synerise/ds-select` — `Select` for edit state
|
|
158
|
+
- `@synerise/ds-date-picker` — `DatePicker` for edit state
|
|
159
|
+
- `@synerise/ds-form-field` — `FormField` wrapper for label + error
|
|
160
|
+
- `@synerise/ds-utils` — `useOnClickOutside` (Field only)
|
|
161
|
+
- `calculate-size` — measures text pixel width to compute visible rows in TextArea
|
|
162
|
+
- `@synerise/ds-tooltip` — suffix tooltip in inactive state
|
|
163
|
+
|
|
164
|
+
## Implementation notes
|
|
165
|
+
|
|
166
|
+
- **Active/inactive toggle** — all sub-components maintain local `active` and `blurred` state. `errorText || error` forces the active/edit view.
|
|
167
|
+
- **`SubtleForm()` returns `null`** — the main component is a namespace-only wrapper; calling it renders nothing.
|
|
168
|
+
- **`inputProps` is required on `SubtleForm.Input`** — not optional in `SubtleInputProps`; pass `inputProps={{}}` if you have no extra props.
|
|
169
|
+
- **`activeProp` on DatePicker is unused in logic** — the prop is declared but not wired into the state machine (only `error` triggers the forced active path).
|
|
170
|
+
- **Deep import in Storybook** — stories import `@synerise/ds-subtle-form/dist/Elements/DatePicker/utils` directly. This is a fragile deep path not covered by public exports.
|
|
171
|
+
- **Only TextArea has tests** — Input, Select, DatePicker, and Field have no spec files.
|
|
172
|
+
- **Uses Vitest**.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synerise/ds-subtle-form",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.8",
|
|
4
4
|
"description": "SubtleForm 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,13 +42,13 @@
|
|
|
41
42
|
],
|
|
42
43
|
"types": "dist/index.d.ts",
|
|
43
44
|
"dependencies": {
|
|
44
|
-
"@synerise/ds-date-picker": "^1.4.
|
|
45
|
-
"@synerise/ds-form-field": "^1.3.
|
|
46
|
-
"@synerise/ds-icon": "^1.18.
|
|
47
|
-
"@synerise/ds-input": "^1.7.
|
|
48
|
-
"@synerise/ds-select": "^1.3.
|
|
49
|
-
"@synerise/ds-tooltip": "^1.5.
|
|
50
|
-
"@synerise/ds-utils": "^1.10.
|
|
45
|
+
"@synerise/ds-date-picker": "^1.4.22",
|
|
46
|
+
"@synerise/ds-form-field": "^1.3.24",
|
|
47
|
+
"@synerise/ds-icon": "^1.18.5",
|
|
48
|
+
"@synerise/ds-input": "^1.7.13",
|
|
49
|
+
"@synerise/ds-select": "^1.3.34",
|
|
50
|
+
"@synerise/ds-tooltip": "^1.5.4",
|
|
51
|
+
"@synerise/ds-utils": "^1.10.2",
|
|
51
52
|
"calculate-size": "^1.1.1"
|
|
52
53
|
},
|
|
53
54
|
"peerDependencies": {
|
|
@@ -57,5 +58,5 @@
|
|
|
57
58
|
"styled-components": "^5.3.3",
|
|
58
59
|
"vitest": "4"
|
|
59
60
|
},
|
|
60
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "d0a43cc43d8528a36f105aceea52ab470edb71d9"
|
|
61
62
|
}
|