@qoretechnologies/reqraft 0.10.65 → 0.10.66-pr.145.g32331ea
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/form/engine/CompactRow.d.ts.map +1 -1
- package/dist/components/form/engine/CompactRow.js +128 -24
- package/dist/components/form/engine/CompactRow.js.map +1 -1
- package/dist/components/form/engine/CompactToolbar.d.ts.map +1 -1
- package/dist/components/form/engine/CompactToolbar.js +78 -15
- package/dist/components/form/engine/CompactToolbar.js.map +1 -1
- package/dist/components/form/engine/FormEngine.d.ts +48 -1
- package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
- package/dist/components/form/engine/FormEngine.js +243 -85
- package/dist/components/form/engine/FormEngine.js.map +1 -1
- package/dist/components/form/engine/OptionFieldMessages.d.ts +18 -2
- package/dist/components/form/engine/OptionFieldMessages.d.ts.map +1 -1
- package/dist/components/form/engine/OptionFieldMessages.js +22 -3
- package/dist/components/form/engine/OptionFieldMessages.js.map +1 -1
- package/dist/components/form/engine/_structuredData/SchemaDataView.d.ts.map +1 -1
- package/dist/components/form/engine/_structuredData/SchemaDataView.js +27 -1
- package/dist/components/form/engine/_structuredData/SchemaDataView.js.map +1 -1
- package/dist/components/form/engine/compactRowContext.d.ts +5 -0
- package/dist/components/form/engine/compactRowContext.d.ts.map +1 -1
- package/dist/components/form/engine/compactRowContext.js.map +1 -1
- package/dist/components/form/engine/compactRowStyles.d.ts +12 -0
- package/dist/components/form/engine/compactRowStyles.d.ts.map +1 -1
- package/dist/components/form/engine/compactRowStyles.js +72 -39
- package/dist/components/form/engine/compactRowStyles.js.map +1 -1
- package/dist/components/form/engine/compactToolbarContext.d.ts +3 -0
- package/dist/components/form/engine/compactToolbarContext.d.ts.map +1 -1
- package/dist/components/form/engine/compactToolbarContext.js.map +1 -1
- package/dist/components/form/engine/formAppearance.d.ts +48 -0
- package/dist/components/form/engine/formAppearance.d.ts.map +1 -0
- package/dist/components/form/engine/formAppearance.js +50 -0
- package/dist/components/form/engine/formAppearance.js.map +1 -0
- package/dist/components/form/engine/readFirst.d.ts +14 -2
- package/dist/components/form/engine/readFirst.d.ts.map +1 -1
- package/dist/components/form/engine/readFirst.js +6 -2
- package/dist/components/form/engine/readFirst.js.map +1 -1
- package/dist/components/form/engine/rowFocus.d.ts +9 -1
- package/dist/components/form/engine/rowFocus.d.ts.map +1 -1
- package/dist/components/form/engine/rowFocus.js +17 -5
- package/dist/components/form/engine/rowFocus.js.map +1 -1
- package/dist/components/form/fields/ChoiceGroupHeading.d.ts +21 -0
- package/dist/components/form/fields/ChoiceGroupHeading.d.ts.map +1 -0
- package/dist/components/form/fields/ChoiceGroupHeading.js +33 -0
- package/dist/components/form/fields/ChoiceGroupHeading.js.map +1 -0
- package/dist/components/form/fields/Field.d.ts.map +1 -1
- package/dist/components/form/fields/Field.js +5 -3
- package/dist/components/form/fields/Field.js.map +1 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.d.ts.map +1 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.js +4 -2
- package/dist/components/form/fields/allowed-values/AllowedValues.js.map +1 -1
- package/dist/components/form/fields/radio-group/RadioGroup.d.ts.map +1 -1
- package/dist/components/form/fields/radio-group/RadioGroup.js +13 -7
- package/dist/components/form/fields/radio-group/RadioGroup.js.map +1 -1
- package/dist/components/form/index.d.ts +1 -0
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/index.js +1 -0
- package/dist/components/form/index.js.map +1 -1
- package/dist/components/supportTicket/TicketHeader.d.ts.map +1 -1
- package/dist/components/supportTicket/TicketHeader.js +4 -1
- package/dist/components/supportTicket/TicketHeader.js.map +1 -1
- package/dist/components/supportTicket/TicketReplyBox.d.ts.map +1 -1
- package/dist/components/supportTicket/TicketReplyBox.js +29 -10
- package/dist/components/supportTicket/TicketReplyBox.js.map +1 -1
- package/package.json +1 -1
- package/src/components/form/engine/CompactRow.tsx +141 -22
- package/src/components/form/engine/CompactToolbar.tsx +85 -16
- package/src/components/form/engine/FormEngine.stories.tsx +25 -13
- package/src/components/form/engine/FormEngine.tsx +358 -77
- package/src/components/form/engine/FormEngineAppearance.stories.tsx +540 -0
- package/src/components/form/engine/FormEngineStickyHeaders.stories.tsx +5 -1
- package/src/components/form/engine/OptionFieldMessages.tsx +73 -2
- package/src/components/form/engine/_structuredData/SchemaDataView.tsx +17 -4
- package/src/components/form/engine/compactRowContext.ts +5 -0
- package/src/components/form/engine/compactRowStyles.ts +218 -38
- package/src/components/form/engine/compactToolbarContext.ts +3 -0
- package/src/components/form/engine/formAppearance.ts +78 -0
- package/src/components/form/engine/readFirst.ts +16 -3
- package/src/components/form/engine/rowFocus.ts +17 -6
- package/src/components/form/fields/ChoiceGroupHeading.tsx +38 -0
- package/src/components/form/fields/Field.tsx +6 -5
- package/src/components/form/fields/allowed-values/AllowedValues.tsx +7 -4
- package/src/components/form/fields/radio-group/RadioGroup.tsx +13 -7
- package/src/components/form/index.tsx +1 -0
- package/src/components/supportTicket/TicketHeader.tsx +2 -1
- package/src/components/supportTicket/TicketReplyBox.stories.tsx +17 -2
- package/src/components/supportTicket/TicketReplyBox.tsx +27 -5
|
@@ -11,9 +11,10 @@ import {
|
|
|
11
11
|
} from '@qoretechnologies/reqore/dist/components/Dropdown/list';
|
|
12
12
|
import { useReqoreTheme } from '@qoretechnologies/reqore/dist/hooks/useTheme';
|
|
13
13
|
import React, { memo } from 'react';
|
|
14
|
-
import styled from 'styled-components';
|
|
14
|
+
import styled, { css } from 'styled-components';
|
|
15
15
|
import { useContext } from 'use-context-selector';
|
|
16
16
|
import { CompactToolbarContext, TCompactSort } from './compactToolbarContext';
|
|
17
|
+
import { useIsCalmForm } from './formAppearance';
|
|
17
18
|
|
|
18
19
|
// Field sort modes, listed in the Fields menu's "Sort by" submenu. 'schema' is
|
|
19
20
|
// the default (the schema's declared order); the rest reorder within each group.
|
|
@@ -28,11 +29,21 @@ const SORT_MODES: { value: TCompactSort; label: string; tooltip: string }[] = [
|
|
|
28
29
|
// "Focus" header: a summary line ({pct}% complete · {set}/{total} set ·
|
|
29
30
|
// {attention} need attention →) above a SEGMENTED meter — a green run (set) then
|
|
30
31
|
// an amber run (needs attention) then the empty remainder.
|
|
31
|
-
const StyledCompletion = styled.div
|
|
32
|
+
const StyledCompletion = styled.div<{ $calm?: boolean }>`
|
|
32
33
|
display: flex;
|
|
33
34
|
flex-flow: column;
|
|
34
35
|
gap: 8px;
|
|
35
36
|
padding: 0 2px;
|
|
37
|
+
/* Calm: one line — the summary, then a short meter beside it — that wraps
|
|
38
|
+
the meter under the words where there is no room for both. */
|
|
39
|
+
${({ $calm }) =>
|
|
40
|
+
$calm ?
|
|
41
|
+
css`
|
|
42
|
+
flex-flow: row wrap;
|
|
43
|
+
align-items: center;
|
|
44
|
+
gap: 6px 14px;
|
|
45
|
+
`
|
|
46
|
+
: ''}
|
|
36
47
|
`;
|
|
37
48
|
const StyledCompletionLine = styled.div`
|
|
38
49
|
display: flex;
|
|
@@ -46,11 +57,20 @@ const StyledMeter = styled.div<{
|
|
|
46
57
|
$track: string;
|
|
47
58
|
$set_c: string;
|
|
48
59
|
$att_c: string;
|
|
60
|
+
/** Calm: a short meter beside the summary instead of a full-width bar. */
|
|
61
|
+
$calm?: boolean;
|
|
49
62
|
}>`
|
|
50
63
|
position: relative;
|
|
51
64
|
height: 4px;
|
|
52
|
-
border-radius:
|
|
65
|
+
border-radius: ${({ $calm }) => ($calm ? 2 : 3)}px;
|
|
53
66
|
width: 100%;
|
|
67
|
+
${({ $calm }) =>
|
|
68
|
+
$calm ?
|
|
69
|
+
css`
|
|
70
|
+
flex: 1 1 160px;
|
|
71
|
+
max-width: 360px;
|
|
72
|
+
`
|
|
73
|
+
: ''}
|
|
54
74
|
overflow: hidden;
|
|
55
75
|
background: ${({ $track }) => $track};
|
|
56
76
|
/* No per-segment radius — the container's overflow:hidden + radius rounds only
|
|
@@ -113,7 +133,9 @@ export const CompactToolbar = memo((reqoreProps: Partial<IReqoreControlGroupProp
|
|
|
113
133
|
readOnly,
|
|
114
134
|
invalidCount,
|
|
115
135
|
attentionCount,
|
|
136
|
+
attentionFaultCount,
|
|
116
137
|
completion,
|
|
138
|
+
showInvalidOnly,
|
|
117
139
|
onToggleInvalidOnly,
|
|
118
140
|
hasMultipleOptions,
|
|
119
141
|
compactQuery,
|
|
@@ -135,16 +157,40 @@ export const CompactToolbar = memo((reqoreProps: Partial<IReqoreControlGroupProp
|
|
|
135
157
|
} = useContext(CompactToolbarContext);
|
|
136
158
|
|
|
137
159
|
const theme = useReqoreTheme();
|
|
160
|
+
const calm = useIsCalmForm();
|
|
138
161
|
const intents = (theme.intents || {}) as Record<string, string>;
|
|
162
|
+
/* "N need attention →" / "N to fill in →" is a toggle (show only those fields), so it
|
|
163
|
+
is one: a button a keyboard reaches, which says whether it is on. A host that turns
|
|
164
|
+
it on for a person (a blocked submit) reads `aria-pressed` rather than guessing,
|
|
165
|
+
since the toolbar draws a different link once something becomes a fault. */
|
|
166
|
+
const attentionToggleProps = {
|
|
167
|
+
className: 'options-readfirst-attention-link',
|
|
168
|
+
role: 'button',
|
|
169
|
+
tabIndex: 0,
|
|
170
|
+
'aria-pressed': !!showInvalidOnly,
|
|
171
|
+
onClick: onToggleInvalidOnly,
|
|
172
|
+
onKeyDown: (event: React.KeyboardEvent) => {
|
|
173
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
174
|
+
event.preventDefault();
|
|
175
|
+
onToggleInvalidOnly?.();
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
};
|
|
139
179
|
const cSuccess = intents.success || '#4a7110';
|
|
140
180
|
const cWarning = intents.warning || '#d17c29';
|
|
141
181
|
const cText = (theme.text?.color as string) || '#e8e8e8';
|
|
142
182
|
const cTrack = `${cText}1f`;
|
|
183
|
+
// Calm: what is done is grey — finished work needs nobody — and only the
|
|
184
|
+
// outstanding part (the amber run, the "need attention" link) is coloured.
|
|
185
|
+
const cDone = calm ? `${cText}8c` : cSuccess;
|
|
186
|
+
const cQuiet = `${cText}a6`;
|
|
143
187
|
// The GREEN run is what is done, not merely what has a value: a field that is
|
|
144
188
|
// set but flagged belongs to the amber run, and counting it twice pushed that
|
|
145
189
|
// run off the end of the track.
|
|
146
190
|
const setPct = completion.total ? (completion.done / completion.total) * 100 : 0;
|
|
147
|
-
|
|
191
|
+
// The amber run is what is WRONG. On a new form the required fields are only still
|
|
192
|
+
// to fill in, so the track shows them as not done yet, without amber.
|
|
193
|
+
const attentionPct = completion.total ? (attentionFaultCount / completion.total) * 100 : 0;
|
|
148
194
|
|
|
149
195
|
return (
|
|
150
196
|
<ReqoreControlGroup
|
|
@@ -161,11 +207,19 @@ export const CompactToolbar = memo((reqoreProps: Partial<IReqoreControlGroupProp
|
|
|
161
207
|
work. The read view lists what is set, and that is the whole
|
|
162
208
|
answer. */}
|
|
163
209
|
{parts.completion && completion.total && !readOnly ?
|
|
164
|
-
<StyledCompletion className='options-readfirst-completion'>
|
|
210
|
+
<StyledCompletion className='options-readfirst-completion' $calm={calm}>
|
|
165
211
|
<StyledCompletionLine>
|
|
166
212
|
<StyledSummary
|
|
167
213
|
className='options-readfirst-status'
|
|
168
|
-
|
|
214
|
+
// Calm: the word in the text colour. "Ready" is not a healthy
|
|
215
|
+
// figure to celebrate in green, and "Incomplete" is said in amber
|
|
216
|
+
// by the link beside it — only the outstanding part is coloured.
|
|
217
|
+
$color={
|
|
218
|
+
calm ? cText
|
|
219
|
+
: invalidCount || attentionFaultCount ? cWarning
|
|
220
|
+
: attentionCount ? cText
|
|
221
|
+
: cSuccess
|
|
222
|
+
}
|
|
169
223
|
style={{ fontWeight: 600 }}
|
|
170
224
|
>
|
|
171
225
|
{/* "Ready" is a claim about the whole form, so anything the form
|
|
@@ -179,28 +233,43 @@ export const CompactToolbar = memo((reqoreProps: Partial<IReqoreControlGroupProp
|
|
|
179
233
|
batched mode's per-row chip alone. */}
|
|
180
234
|
{invalidCount || attentionCount ? 'Incomplete' : 'Ready'}
|
|
181
235
|
</StyledSummary>
|
|
182
|
-
<StyledSummary style={{ opacity: 0.5 }}>
|
|
236
|
+
<StyledSummary style={calm ? { color: cQuiet } : { opacity: 0.5 }}>
|
|
183
237
|
· {completion.set}/{completion.total} set
|
|
184
238
|
{attentionCount ? ' ·' : ''}
|
|
185
239
|
</StyledSummary>
|
|
186
|
-
{
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
{attentionCount} need attention →
|
|
240
|
+
{/* Amber only for what is a fault. A new form's required fields are still to
|
|
241
|
+
fill in, which is the next step, not a warning: they are counted apart,
|
|
242
|
+
in the quiet colour. */}
|
|
243
|
+
{attentionFaultCount ?
|
|
244
|
+
<StyledAttentionLink $color={cWarning} {...attentionToggleProps}>
|
|
245
|
+
{attentionFaultCount} need attention →
|
|
193
246
|
</StyledAttentionLink>
|
|
194
247
|
: null}
|
|
195
|
-
|
|
248
|
+
{attentionCount > attentionFaultCount ?
|
|
249
|
+
attentionFaultCount ?
|
|
250
|
+
<StyledSummary style={{ color: cQuiet }}>
|
|
251
|
+
· {attentionCount - attentionFaultCount} to fill in
|
|
252
|
+
</StyledSummary>
|
|
253
|
+
: <StyledAttentionLink $color={cQuiet} {...attentionToggleProps}>
|
|
254
|
+
{attentionCount} to fill in →
|
|
255
|
+
</StyledAttentionLink>
|
|
256
|
+
: null}
|
|
257
|
+
{/* Calm: the percentage is one more quiet figure on the line, not
|
|
258
|
+
a large bold number pinned to the far edge. */}
|
|
259
|
+
{calm ?
|
|
260
|
+
<StyledSummary className='options-readfirst-pct' style={{ color: cQuiet }}>
|
|
261
|
+
· {completion.pct}%
|
|
262
|
+
</StyledSummary>
|
|
263
|
+
: <StyledPct className='options-readfirst-pct'>{completion.pct}%</StyledPct>}
|
|
196
264
|
</StyledCompletionLine>
|
|
197
265
|
<StyledMeter
|
|
198
266
|
className='options-readfirst-completion-bar'
|
|
199
267
|
$set={setPct}
|
|
200
268
|
$attention={attentionPct}
|
|
201
269
|
$track={cTrack}
|
|
202
|
-
$set_c={
|
|
270
|
+
$set_c={cDone}
|
|
203
271
|
$att_c={cWarning}
|
|
272
|
+
$calm={calm}
|
|
204
273
|
/>
|
|
205
274
|
</StyledCompletion>
|
|
206
275
|
: null}
|
|
@@ -41,6 +41,12 @@ import {
|
|
|
41
41
|
import { basicFormValue, getBasicFormOptions as getOptions } from './__fixtures__/basicFormOptions';
|
|
42
42
|
import { chromeFieldBases, metaFieldBases } from './__fixtures__/fieldChromeOptions';
|
|
43
43
|
|
|
44
|
+
/** The first status box: "To fill in" while nothing in it is a fault (a new form),
|
|
45
|
+
* "Needs attention" once something is. Stories about which box a field lands in find
|
|
46
|
+
* it under either name. */
|
|
47
|
+
const FIRST_BOX = /^(Needs attention|To fill in)$/;
|
|
48
|
+
const FIRST_BOX_PREFIX = /^(Needs attention|To fill in)/;
|
|
49
|
+
|
|
44
50
|
// schema data
|
|
45
51
|
|
|
46
52
|
const TestOptionsWithRequiredGroups: IOptionsSchema = {
|
|
@@ -2243,6 +2249,7 @@ export const CompactLockedRequiredNeedsNoAttention: Story = {
|
|
|
2243
2249
|
await expect(document.querySelector('[data-field="min"]')).toBeTruthy();
|
|
2244
2250
|
await expect(document.querySelector('[data-field="max"]')).toBeTruthy();
|
|
2245
2251
|
await _testsWaitForTextToNotExist('Needs attention');
|
|
2252
|
+
await _testsWaitForTextToNotExist('To fill in');
|
|
2246
2253
|
// Nothing the author can fill in is missing, so the form is Ready — the
|
|
2247
2254
|
// locked fields do not apply until a kind is picked.
|
|
2248
2255
|
await _testsWaitForText('Ready');
|
|
@@ -2266,11 +2273,11 @@ export const CompactUnlockedRequiredNeedsAttention: Story = {
|
|
|
2266
2273
|
value: { kind: { type: 'string', value: 'between' } } as IOptions,
|
|
2267
2274
|
},
|
|
2268
2275
|
play: async () => {
|
|
2269
|
-
await _testsWaitForText(
|
|
2276
|
+
await _testsWaitForText(FIRST_BOX);
|
|
2270
2277
|
await _testsWaitForText('Incomplete');
|
|
2271
2278
|
await _testsWaitForTextToNotExist('Draft');
|
|
2272
2279
|
const attention = [...document.querySelectorAll('.options-readfirst-group')].find((group) =>
|
|
2273
|
-
(group.textContent || '')
|
|
2280
|
+
FIRST_BOX_PREFIX.test(group.textContent || '')
|
|
2274
2281
|
);
|
|
2275
2282
|
await expect(attention).toBeTruthy();
|
|
2276
2283
|
for (const field of ['expected', 'min', 'max']) {
|
|
@@ -3070,6 +3077,7 @@ export const CompactReadOnly: Story = {
|
|
|
3070
3077
|
await _testsWaitForTextToNotExist('Incomplete');
|
|
3071
3078
|
await _testsWaitForTextToNotExist('Draft');
|
|
3072
3079
|
await _testsWaitForTextToNotExist('Needs attention');
|
|
3080
|
+
await _testsWaitForTextToNotExist('To fill in');
|
|
3073
3081
|
await _testsWaitForTextToNotExist('Optional');
|
|
3074
3082
|
// A required field nobody set is listed, unset, with no amber dot.
|
|
3075
3083
|
await _testsWaitForText('Description');
|
|
@@ -3551,6 +3559,7 @@ export const CompactReadOnlyValues: Story = {
|
|
|
3551
3559
|
expect(document.querySelector('.options-readfirst-completion')).toBeNull();
|
|
3552
3560
|
expect(document.querySelector('.options-readfirst-group')).toBeNull();
|
|
3553
3561
|
await _testsWaitForTextToNotExist('Needs attention');
|
|
3562
|
+
await _testsWaitForTextToNotExist('To fill in');
|
|
3554
3563
|
await _testsWaitForTextToNotExist('Optional');
|
|
3555
3564
|
// An optional field nobody set is not listed at all…
|
|
3556
3565
|
await _testsWaitForTextToNotExist('Notes');
|
|
@@ -3932,7 +3941,7 @@ export const CompactValidIdentifierRule: Story = {
|
|
|
3932
3941
|
// The rules-driven validation marks the form as needing attention — the
|
|
3933
3942
|
// dedicated "Needs attention" box (and the header link) signal it.
|
|
3934
3943
|
await _testsWaitForText('Incomplete');
|
|
3935
|
-
await _testsWaitForText(
|
|
3944
|
+
await _testsWaitForText(FIRST_BOX);
|
|
3936
3945
|
},
|
|
3937
3946
|
};
|
|
3938
3947
|
|
|
@@ -6764,7 +6773,7 @@ export const CompactShowcase: Story = {
|
|
|
6764
6773
|
// Optional box's fold, which scrolls, so the frame is put back afterwards:
|
|
6765
6774
|
// this story's snapshot is the form's top.
|
|
6766
6775
|
const attentionBox = Array.from(document.querySelectorAll('.options-readfirst-group')).find(
|
|
6767
|
-
(group) => (group.textContent || '')
|
|
6776
|
+
(group) => FIRST_BOX_PREFIX.test(group.textContent || '')
|
|
6768
6777
|
);
|
|
6769
6778
|
await expect(
|
|
6770
6779
|
attentionBox?.querySelector('[data-field="optionWithShortDescription"]')
|
|
@@ -8092,9 +8101,11 @@ export const CompactExpressionWithoutCatalogue: Story = {
|
|
|
8092
8101
|
* A collapsed ReqorePanel unmounts its content, so "has no
|
|
8093
8102
|
* `.reqore-panel-content`" IS the collapsed assertion. */
|
|
8094
8103
|
const findStatusBox = (title: string) =>
|
|
8095
|
-
Array.from(document.querySelectorAll('.options-readfirst-group')).find((panel) =>
|
|
8096
|
-
panel.querySelector('.reqore-panel-title')?.textContent
|
|
8097
|
-
|
|
8104
|
+
Array.from(document.querySelectorAll('.options-readfirst-group')).find((panel) => {
|
|
8105
|
+
const heading = panel.querySelector('.reqore-panel-title')?.textContent ?? '';
|
|
8106
|
+
// The first box is "To fill in" until something in it is a fault.
|
|
8107
|
+
return title === 'Needs attention' ? FIRST_BOX_PREFIX.test(heading) : heading.includes(title);
|
|
8108
|
+
});
|
|
8098
8109
|
|
|
8099
8110
|
const expectBoxCollapsed = async (title: string) => {
|
|
8100
8111
|
await waitFor(
|
|
@@ -9417,7 +9428,7 @@ export const ANewFormSaysWhatIsRequired: Story = {
|
|
|
9417
9428
|
docs: {
|
|
9418
9429
|
description: {
|
|
9419
9430
|
story:
|
|
9420
|
-
'A brand-new form with two empty required fields. Each says "This field is required" from the start, including the first one, which opens for editing, without waiting for the author to visit it.',
|
|
9431
|
+
'A brand-new form with two empty required fields. Each says "This field is required" from the start, including the first one, which opens for editing, without waiting for the author to visit it. Saying what is required is not saying something is wrong: the first box reads "To fill in", in the quiet colour, until a field has been visited and left empty.',
|
|
9421
9432
|
},
|
|
9422
9433
|
},
|
|
9423
9434
|
},
|
|
@@ -9429,7 +9440,8 @@ export const ANewFormSaysWhatIsRequired: Story = {
|
|
|
9429
9440
|
expandFirstRequired: true,
|
|
9430
9441
|
},
|
|
9431
9442
|
play: async ({ canvasElement }) => {
|
|
9432
|
-
await _testsWaitForText('
|
|
9443
|
+
await _testsWaitForText('To fill in');
|
|
9444
|
+
await _testsWaitForTextToNotExist('Needs attention');
|
|
9433
9445
|
await waitFor(() => {
|
|
9434
9446
|
const title = canvasElement.querySelector('[data-field="title"]');
|
|
9435
9447
|
const owner = canvasElement.querySelector('[data-field="owner"]');
|
|
@@ -9551,7 +9563,7 @@ export const AMovedRowInViewIsNotScrolled: Story = {
|
|
|
9551
9563
|
options: MovedRowSchema,
|
|
9552
9564
|
},
|
|
9553
9565
|
play: async () => {
|
|
9554
|
-
await _testsWaitForText(
|
|
9566
|
+
await _testsWaitForText(FIRST_BOX);
|
|
9555
9567
|
const watch = watchRowScrolls();
|
|
9556
9568
|
try {
|
|
9557
9569
|
const scroller = movedRowScroller();
|
|
@@ -9610,7 +9622,7 @@ export const AMovedRowLandsClearOfThePinnedHeader: Story = {
|
|
|
9610
9622
|
await scrolled;
|
|
9611
9623
|
const row = document.querySelector<HTMLElement>('.readfirst-row[data-field="owner"]')!;
|
|
9612
9624
|
const attention = [...document.querySelectorAll<HTMLElement>('.options-readfirst-group')].find(
|
|
9613
|
-
(group) => (group.textContent || '')
|
|
9625
|
+
(group) => FIRST_BOX_PREFIX.test(group.textContent || '')
|
|
9614
9626
|
)!;
|
|
9615
9627
|
const header = attention.querySelector<HTMLElement>(':scope > .reqore-panel-title')!;
|
|
9616
9628
|
const rowRect = row.getBoundingClientRect();
|
|
@@ -9634,12 +9646,12 @@ export const AMovedRowLandsClearOfThePinnedHeader: Story = {
|
|
|
9634
9646
|
* slide UNDER the toolbar, never over it. Each step waits on `scrollend`.
|
|
9635
9647
|
*/
|
|
9636
9648
|
const assertBoxHeaderSlidesUnderToolbar = async (scroller: HTMLElement) => {
|
|
9637
|
-
await _testsWaitForText(
|
|
9649
|
+
await _testsWaitForText(FIRST_BOX);
|
|
9638
9650
|
const toolbar = document.querySelector<HTMLElement>(
|
|
9639
9651
|
'.options-readfirst-scroll > .reqore-panel > .reqore-panel-title'
|
|
9640
9652
|
)!;
|
|
9641
9653
|
const box = [...document.querySelectorAll<HTMLElement>('.options-readfirst-group')].find(
|
|
9642
|
-
(group) => (group.textContent || '')
|
|
9654
|
+
(group) => FIRST_BOX_PREFIX.test(group.textContent || '')
|
|
9643
9655
|
)!;
|
|
9644
9656
|
const header = box.querySelector<HTMLElement>(':scope > .reqore-panel-title')!;
|
|
9645
9657
|
const scrollBy = async (delta: number) => {
|