@qoretechnologies/reqraft 0.10.2 → 0.10.5

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.
Files changed (74) hide show
  1. package/.claude/CLAUDE.md +5 -0
  2. package/design/COMPACT_ENGINE_REDESIGN.md +156 -0
  3. package/design/FORM_ENGINE_COMPACT_UX_PLAN.md +353 -0
  4. package/dist/components/form/engine/CompactRow.d.ts.map +1 -1
  5. package/dist/components/form/engine/CompactRow.js +158 -101
  6. package/dist/components/form/engine/CompactRow.js.map +1 -1
  7. package/dist/components/form/engine/CompactToolbar.d.ts.map +1 -1
  8. package/dist/components/form/engine/CompactToolbar.js +122 -105
  9. package/dist/components/form/engine/CompactToolbar.js.map +1 -1
  10. package/dist/components/form/engine/FormEngine.d.ts +9 -1
  11. package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
  12. package/dist/components/form/engine/FormEngine.js +272 -82
  13. package/dist/components/form/engine/FormEngine.js.map +1 -1
  14. package/dist/components/form/engine/compactRowStyles.d.ts +6 -3
  15. package/dist/components/form/engine/compactRowStyles.d.ts.map +1 -1
  16. package/dist/components/form/engine/compactRowStyles.js +76 -49
  17. package/dist/components/form/engine/compactRowStyles.js.map +1 -1
  18. package/dist/components/form/engine/compactToolbarContext.d.ts +1 -0
  19. package/dist/components/form/engine/compactToolbarContext.d.ts.map +1 -1
  20. package/dist/components/form/engine/compactToolbarContext.js.map +1 -1
  21. package/dist/components/form/engine/readFirst.d.ts +19 -0
  22. package/dist/components/form/engine/readFirst.d.ts.map +1 -1
  23. package/dist/components/form/engine/readFirst.js +22 -1
  24. package/dist/components/form/engine/readFirst.js.map +1 -1
  25. package/dist/components/form/engine/variants/VariantCalmTable.d.ts +6 -0
  26. package/dist/components/form/engine/variants/VariantCalmTable.d.ts.map +1 -0
  27. package/dist/components/form/engine/variants/VariantCalmTable.js +94 -0
  28. package/dist/components/form/engine/variants/VariantCalmTable.js.map +1 -0
  29. package/dist/components/form/engine/variants/VariantCards.d.ts +6 -0
  30. package/dist/components/form/engine/variants/VariantCards.d.ts.map +1 -0
  31. package/dist/components/form/engine/variants/VariantCards.js +80 -0
  32. package/dist/components/form/engine/variants/VariantCards.js.map +1 -0
  33. package/dist/components/form/engine/variants/VariantFocus.d.ts +7 -0
  34. package/dist/components/form/engine/variants/VariantFocus.d.ts.map +1 -0
  35. package/dist/components/form/engine/variants/VariantFocus.js +138 -0
  36. package/dist/components/form/engine/variants/VariantFocus.js.map +1 -0
  37. package/dist/components/form/engine/variants/VariantMinimal.d.ts +6 -0
  38. package/dist/components/form/engine/variants/VariantMinimal.d.ts.map +1 -0
  39. package/dist/components/form/engine/variants/VariantMinimal.js +73 -0
  40. package/dist/components/form/engine/variants/VariantMinimal.js.map +1 -0
  41. package/dist/components/form/engine/variants/focusDemo.d.ts +13 -0
  42. package/dist/components/form/engine/variants/focusDemo.d.ts.map +1 -0
  43. package/dist/components/form/engine/variants/focusDemo.js +139 -0
  44. package/dist/components/form/engine/variants/focusDemo.js.map +1 -0
  45. package/dist/components/form/engine/variants/variantModel.d.ts +70 -0
  46. package/dist/components/form/engine/variants/variantModel.d.ts.map +1 -0
  47. package/dist/components/form/engine/variants/variantModel.js +133 -0
  48. package/dist/components/form/engine/variants/variantModel.js.map +1 -0
  49. package/dist/components/form/engine/variants/variantParts.d.ts +79 -0
  50. package/dist/components/form/engine/variants/variantParts.d.ts.map +1 -0
  51. package/dist/components/form/engine/variants/variantParts.js +191 -0
  52. package/dist/components/form/engine/variants/variantParts.js.map +1 -0
  53. package/dist/components/form/fields/auto/AutoFormField.d.ts +3 -0
  54. package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
  55. package/dist/components/form/fields/auto/AutoFormField.js +5 -2
  56. package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
  57. package/package.json +1 -1
  58. package/src/components/form/engine/CompactRow.tsx +273 -258
  59. package/src/components/form/engine/CompactToolbar.tsx +112 -85
  60. package/src/components/form/engine/FormEngine.stories.tsx +239 -115
  61. package/src/components/form/engine/FormEngine.tsx +332 -83
  62. package/src/components/form/engine/compactRowStyles.ts +221 -144
  63. package/src/components/form/engine/compactToolbarContext.ts +1 -0
  64. package/src/components/form/engine/readFirst.ts +35 -0
  65. package/src/components/form/engine/variants/FormEngineVariants.stories.tsx +119 -0
  66. package/src/components/form/engine/variants/VariantCalmTable.tsx +242 -0
  67. package/src/components/form/engine/variants/VariantCards.tsx +212 -0
  68. package/src/components/form/engine/variants/VariantFocus.tsx +382 -0
  69. package/src/components/form/engine/variants/VariantMinimal.tsx +170 -0
  70. package/src/components/form/engine/variants/focusDemo.ts +145 -0
  71. package/src/components/form/engine/variants/variantModel.ts +216 -0
  72. package/src/components/form/engine/variants/variantParts.tsx +313 -0
  73. package/src/components/form/fields/auto/AutoFormField.stories.tsx +9 -2
  74. package/src/components/form/fields/auto/AutoFormField.tsx +8 -0
@@ -3,11 +3,8 @@ import {
3
3
  ReqoreControlGroup,
4
4
  ReqoreDropdown,
5
5
  ReqoreInput,
6
- ReqoreMessage,
7
- ReqoreProgress,
8
- ReqoreSpan,
9
- ReqoreTag,
10
6
  } from '@qoretechnologies/reqore';
7
+ import { useReqoreTheme } from '@qoretechnologies/reqore/dist/hooks/useTheme';
11
8
  import { IReqoreControlGroupProps } from '@qoretechnologies/reqore/dist/components/ControlGroup';
12
9
  import {
13
10
  IReqoreDropdownItem,
@@ -28,20 +25,73 @@ const SORT_MODES: { value: TCompactSort; label: string; tooltip: string }[] = [
28
25
  { value: 'invalid', label: 'Invalid first', tooltip: 'Fields needing attention first' },
29
26
  ];
30
27
 
31
- // Custom flex, not ReqoreControlGroup: the meter needs the middle bar to absorb
32
- // all width changes while the fixed-width labels never shrink/truncate and a
33
- // 12px gap that isn't on ReqoreControlGroup's gapSize scale (5 or 18). The
34
- // `flex: 1; min-width: 0` makes only the bar yield as the row narrows.
28
+ // "Focus" header: a summary line ({pct}% complete · {set}/{total} set ·
29
+ // {attention} need attention →) above a SEGMENTED metera green run (set) then
30
+ // an amber run (needs attention) then the empty remainder.
35
31
  const StyledCompletion = styled.div`
36
32
  display: flex;
37
- align-items: center;
38
- gap: 12px;
33
+ flex-flow: column;
34
+ gap: 8px;
39
35
  padding: 0 2px;
40
- & > .reqore-progress {
41
- flex: 1;
42
- min-width: 0;
36
+ `;
37
+ const StyledCompletionLine = styled.div`
38
+ display: flex;
39
+ align-items: baseline;
40
+ gap: 10px;
41
+ flex-wrap: wrap;
42
+ `;
43
+ const StyledMeter = styled.div<{ $set: number; $attention: number; $track: string; $set_c: string; $att_c: string }>`
44
+ position: relative;
45
+ height: 4px;
46
+ border-radius: 3px;
47
+ width: 100%;
48
+ overflow: hidden;
49
+ background: ${({ $track }) => $track};
50
+ /* No per-segment radius — the container's overflow:hidden + radius rounds only
51
+ the OUTER corners, so the green/amber runs meet flush (no notch). */
52
+ &::before,
53
+ &::after {
54
+ content: '';
55
+ position: absolute;
56
+ top: 0;
57
+ bottom: 0;
58
+ }
59
+ /* green run: 0 → set% */
60
+ &::before {
61
+ left: 0;
62
+ width: ${({ $set }) => $set}%;
63
+ background: ${({ $set_c }) => $set_c};
64
+ }
65
+ /* amber run: set% → set%+attention% */
66
+ &::after {
67
+ left: ${({ $set }) => $set}%;
68
+ width: ${({ $attention }) => $attention}%;
69
+ background: ${({ $att_c }) => $att_c};
43
70
  }
44
71
  `;
72
+ // One shared text size for the whole summary line, so "Draft", "1/6 set" and
73
+ // "N need attention" all read at the same scale (no chips, no size jumps).
74
+ const StyledSummary = styled.span<{ $color?: string }>`
75
+ font-size: 13px;
76
+ white-space: nowrap;
77
+ color: ${({ $color }) => $color || 'inherit'};
78
+ `;
79
+ const StyledAttentionLink = styled.span<{ $color: string }>`
80
+ color: ${({ $color }) => $color};
81
+ font-size: 13px;
82
+ cursor: pointer;
83
+ white-space: nowrap;
84
+ &:hover {
85
+ text-decoration: underline;
86
+ }
87
+ `;
88
+ // The percentage, pushed to the far right of the summary line.
89
+ const StyledPct = styled.span`
90
+ margin-left: auto;
91
+ font-weight: 700;
92
+ font-size: 17px;
93
+ white-space: nowrap;
94
+ `;
45
95
 
46
96
  /**
47
97
  * The compact form's sticky toolbar (completion meter + field filter + "Fields"
@@ -55,8 +105,8 @@ export const CompactToolbar = memo((reqoreProps: Partial<IReqoreControlGroupProp
55
105
  const {
56
106
  readOnly,
57
107
  invalidCount,
108
+ attentionCount,
58
109
  completion,
59
- showInvalidOnly,
60
110
  onToggleInvalidOnly,
61
111
  hasMultipleOptions,
62
112
  compactQuery,
@@ -70,7 +120,6 @@ export const CompactToolbar = memo((reqoreProps: Partial<IReqoreControlGroupProp
70
120
  showAllDescriptions,
71
121
  onToggleAllDescriptions,
72
122
  filteredCount,
73
- optionalFields,
74
123
  canRevert,
75
124
  onAddOptionalField,
76
125
  onAddAll,
@@ -78,51 +127,53 @@ export const CompactToolbar = memo((reqoreProps: Partial<IReqoreControlGroupProp
78
127
  onRevertAll,
79
128
  } = useContext(CompactToolbarContext);
80
129
 
130
+ const theme = useReqoreTheme();
131
+ const intents = (theme.intents || {}) as Record<string, string>;
132
+ const cSuccess = intents.success || '#4a7110';
133
+ const cWarning = intents.warning || '#d17c29';
134
+ const cText = (theme.text?.color as string) || '#e8e8e8';
135
+ const cTrack = `${cText}1f`;
136
+ const setPct = completion.total ? (completion.set / completion.total) * 100 : 0;
137
+ const attentionPct = completion.total ? (attentionCount / completion.total) * 100 : 0;
138
+
81
139
  return (
82
140
  <ReqoreControlGroup {...reqoreProps} vertical fluid fixed={false} gapSize='big'>
83
141
  {completion.total ?
84
142
  <StyledCompletion className='options-readfirst-completion'>
85
- {!readOnly ?
86
- invalidCount ?
87
- <ReqoreTag
143
+ <StyledCompletionLine>
144
+ {!readOnly ?
145
+ <StyledSummary
88
146
  className='options-readfirst-status'
89
- label='Draft'
90
- intent='warning'
91
- icon='EditLine'
92
- minimal
93
- flat
94
- size='tiny'
95
- compact
96
- fixed
97
- effect={{ uppercase: true, spaced: 1 }}
98
- />
99
- : <ReqoreTag
100
- className='options-readfirst-status'
101
- label='Ready'
102
- intent='success'
103
- icon='CheckLine'
104
- minimal
105
- flat
106
- size='tiny'
107
- compact
108
- fixed
109
- effect={{ uppercase: true, spaced: 1 }}
110
- />
111
-
112
- : null}
113
- <ReqoreSpan size='small' effect={{ opacity: 0.7, noWrap: true }}>
114
- {completion.set} / {completion.total} fields set
115
- </ReqoreSpan>
116
- <ReqoreProgress
147
+ $color={invalidCount ? cWarning : cSuccess}
148
+ style={{ fontWeight: 600 }}
149
+ >
150
+ {invalidCount ? 'Draft' : 'Ready'}
151
+ </StyledSummary>
152
+ : null}
153
+ <StyledSummary style={{ opacity: 0.5 }}>
154
+ {!readOnly ? '· ' : ''}
155
+ {completion.set}/{completion.total} set
156
+ {!readOnly && attentionCount ? ' ·' : ''}
157
+ </StyledSummary>
158
+ {!readOnly && attentionCount ?
159
+ <StyledAttentionLink
160
+ $color={cWarning}
161
+ className='options-readfirst-attention-link'
162
+ onClick={onToggleInvalidOnly}
163
+ >
164
+ {attentionCount} need attention →
165
+ </StyledAttentionLink>
166
+ : null}
167
+ <StyledPct>{completion.pct}%</StyledPct>
168
+ </StyledCompletionLine>
169
+ <StyledMeter
117
170
  className='options-readfirst-completion-bar'
118
- value={completion.pct}
119
- intent={completion.set === completion.total ? 'success' : 'info'}
120
- size='normal'
121
- flat
171
+ $set={setPct}
172
+ $attention={attentionPct}
173
+ $track={cTrack}
174
+ $set_c={cSuccess}
175
+ $att_c={cWarning}
122
176
  />
123
- <ReqoreSpan size='small' effect={{ opacity: 0.7, noWrap: true }}>
124
- {completion.pct}%
125
- </ReqoreSpan>
126
177
  </StyledCompletion>
127
178
  : null}
128
179
 
@@ -147,10 +198,10 @@ export const CompactToolbar = memo((reqoreProps: Partial<IReqoreControlGroupProp
147
198
  {!readOnly ?
148
199
  <ReqoreDropdown
149
200
  fixed
150
- minimal
201
+ flat
151
202
  filterable
152
203
  icon='Filter3Line'
153
- label='Fields'
204
+ tooltip='Fields'
154
205
  className='options-readfirst-fields'
155
206
  intent={requiredOnly ? 'info' : undefined}
156
207
  badge={requiredOnly ? 'Required only' : undefined}
@@ -216,29 +267,18 @@ export const CompactToolbar = memo((reqoreProps: Partial<IReqoreControlGroupProp
216
267
  disabled: !canRevert,
217
268
  onClick: onRevertAll,
218
269
  },
219
- ...(filteredCount ?
220
- [
221
- {
222
- label: 'Add optional fields',
223
- readOnly: true,
224
- disabled: true,
225
- icon: 'AddLine',
226
- },
227
- ]
228
- : []),
229
- ...optionalFields.map((field) => ({
230
- label: field.display_name || field.value,
231
- value: field.value,
232
- description: field.short_desc,
233
- disabled: field.disabled,
234
- })),
270
+ // The individual not-yet-added fields are no longer listed here —
271
+ // they render as addable rows in the Optional box instead. The
272
+ // menu keeps only the bulk actions above (Select all / Default
273
+ // fields / filters).
235
274
  ] as TReqoreDropdownItems
236
275
  }
237
276
  />
238
277
  : null}
239
278
  <ReqoreButton
240
279
  fixed
241
- minimal
280
+ flat
281
+ minimal={showAllDescriptions === true}
242
282
  icon={showAllDescriptions ? 'InformationFill' : 'InformationLine'}
243
283
  className='options-readfirst-descriptions'
244
284
  active={showAllDescriptions}
@@ -248,19 +288,6 @@ export const CompactToolbar = memo((reqoreProps: Partial<IReqoreControlGroupProp
248
288
  />
249
289
  </ReqoreControlGroup>
250
290
  : null}
251
- {invalidCount && !readOnly ?
252
- <ReqoreMessage
253
- intent={showInvalidOnly ? 'info' : 'danger'}
254
- opaque={false}
255
- size='small'
256
- className='options-readfirst-invalid-banner'
257
- onClick={onToggleInvalidOnly}
258
- >
259
- {showInvalidOnly ?
260
- 'Showing invalid fields only. Click here again to show all fields.'
261
- : `${invalidCount < 2 ? 'A field is not valid and requires' : `${invalidCount} fields are not valid and require`} attention. Click here to only show invalid fields.`}
262
- </ReqoreMessage>
263
- : null}
264
291
  </ReqoreControlGroup>
265
292
  : null}
266
293
  </ReqoreControlGroup>