@qoretechnologies/reqraft 0.10.16 → 0.10.17
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 +82 -3
- package/dist/components/form/engine/CompactRow.js.map +1 -1
- package/dist/components/form/engine/FormEngine.d.ts +37 -11
- package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
- package/dist/components/form/engine/FormEngine.js +174 -110
- package/dist/components/form/engine/FormEngine.js.map +1 -1
- package/dist/components/form/engine/compactRowContext.d.ts +8 -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.map +1 -1
- package/dist/components/form/engine/compactRowStyles.js +1 -1
- package/dist/components/form/engine/compactRowStyles.js.map +1 -1
- package/dist/components/form/engine/optionActions.d.ts +28 -0
- package/dist/components/form/engine/optionActions.d.ts.map +1 -0
- package/dist/components/form/engine/optionActions.js +18 -0
- package/dist/components/form/engine/optionActions.js.map +1 -0
- package/dist/components/form/engine/readFirst.d.ts +9 -2
- package/dist/components/form/engine/readFirst.d.ts.map +1 -1
- package/dist/components/form/engine/readFirst.js +15 -3
- package/dist/components/form/engine/readFirst.js.map +1 -1
- package/dist/components/form/engine/rendererTypes.d.ts +35 -0
- package/dist/components/form/engine/rendererTypes.d.ts.map +1 -0
- package/dist/components/form/engine/rendererTypes.js +63 -0
- package/dist/components/form/engine/rendererTypes.js.map +1 -0
- package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
- package/dist/components/form/fields/auto/AutoFormField.js +6 -1
- package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
- package/dist/components/form/index.d.ts +2 -0
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/index.js +2 -0
- package/dist/components/form/index.js.map +1 -1
- package/dist/hooks/useMediaQuery.d.ts +24 -0
- package/dist/hooks/useMediaQuery.d.ts.map +1 -0
- package/dist/hooks/useMediaQuery.js +56 -0
- package/dist/hooks/useMediaQuery.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/form/engine/CompactRow.tsx +139 -0
- package/src/components/form/engine/FormEngine.tsx +222 -70
- package/src/components/form/engine/FormEngineRemote.stories.tsx +329 -0
- package/src/components/form/engine/compactRowContext.ts +8 -0
- package/src/components/form/engine/compactRowStyles.ts +30 -0
- package/src/components/form/engine/optionActions.ts +40 -0
- package/src/components/form/engine/readFirst.ts +25 -6
- package/src/components/form/engine/rendererTypes.ts +55 -0
- package/src/components/form/fields/auto/AutoFormField.tsx +6 -1
- package/src/components/form/index.tsx +2 -0
- package/src/hooks/useMediaQuery.ts +61 -0
- package/src/index.tsx +7 -0
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
ReqoreTagGroup,
|
|
11
11
|
} from '@qoretechnologies/reqore';
|
|
12
12
|
import { IReqoreDropdownItem } from '@qoretechnologies/reqore/dist/components/Dropdown/list';
|
|
13
|
+
import { IReqorePanelAction } from '@qoretechnologies/reqore/dist/components/Panel';
|
|
14
|
+
import { resolveOptionActions } from './optionActions';
|
|
13
15
|
import {
|
|
14
16
|
IQorusFormField,
|
|
15
17
|
TQorusForm,
|
|
@@ -107,6 +109,12 @@ const COMPACT_SINGLE_VALUE_TYPES = new Set([
|
|
|
107
109
|
'method-name',
|
|
108
110
|
]);
|
|
109
111
|
|
|
112
|
+
// How many consumer-injected actions may sit inline in a row before the rest
|
|
113
|
+
// overflow into the row's menu. A row's action slot shares space with the
|
|
114
|
+
// value; an unbounded button strip would squeeze the value out, and the
|
|
115
|
+
// consumer controls how many actions it injects.
|
|
116
|
+
const MAX_INLINE_OPTION_ACTIONS = 2;
|
|
117
|
+
|
|
110
118
|
|
|
111
119
|
// One read-first row: label | value | action collapsed; the real editor (the
|
|
112
120
|
// classic renderOption) expanded. `hidden` = search-surfaced optional —
|
|
@@ -176,6 +184,11 @@ export const CompactRow = memo(
|
|
|
176
184
|
);
|
|
177
185
|
const getTypeForOption = useContextSelector(CompactRowContext, (v) => v.getTypeForOption);
|
|
178
186
|
const confirmAction = useContextSelector(CompactRowContext, (v) => v.confirmAction);
|
|
187
|
+
const optionActions = useContextSelector(CompactRowContext, (v) => v.optionActions);
|
|
188
|
+
const collapseOptionActions = useContextSelector(
|
|
189
|
+
CompactRowContext,
|
|
190
|
+
(v) => v.collapseOptionActions
|
|
191
|
+
);
|
|
179
192
|
const renderOption = useContextSelector(CompactRowContext, (v) => v.renderOption);
|
|
180
193
|
const theme = useContextSelector(CompactRowContext, (v) => v.theme);
|
|
181
194
|
const cMuted = useContextSelector(CompactRowContext, (v) => v.cMuted);
|
|
@@ -338,6 +351,97 @@ export const CompactRow = memo(
|
|
|
338
351
|
|
|
339
352
|
const schema = options?.[optionName];
|
|
340
353
|
const label = schema?.display_name || optionName;
|
|
354
|
+
const injectedOptionActions = React.useMemo<IReqorePanelAction[]>(
|
|
355
|
+
() =>
|
|
356
|
+
schema ?
|
|
357
|
+
resolveOptionActions(optionActions, {
|
|
358
|
+
name: optionName,
|
|
359
|
+
schema,
|
|
360
|
+
value: availableOptions?.[optionName],
|
|
361
|
+
}).filter((action) => action.show !== false)
|
|
362
|
+
: [],
|
|
363
|
+
[availableOptions?.[optionName], optionActions, optionName, schema]
|
|
364
|
+
);
|
|
365
|
+
// Which injected actions stay as inline buttons, and which move into the
|
|
366
|
+
// overflow menu. Everything collapses on touch / narrow viewports — a
|
|
367
|
+
// hover-gated button is unreachable without a hover — and anything past the
|
|
368
|
+
// inline cap overflows regardless, so a consumer injecting ten actions can
|
|
369
|
+
// never push the row's value out of view.
|
|
370
|
+
const [inlineOptionActions, menuOptionActions] = React.useMemo<
|
|
371
|
+
[IReqorePanelAction[], IReqorePanelAction[]]
|
|
372
|
+
>(
|
|
373
|
+
() =>
|
|
374
|
+
collapseOptionActions ?
|
|
375
|
+
[[], injectedOptionActions]
|
|
376
|
+
: [
|
|
377
|
+
injectedOptionActions.slice(0, MAX_INLINE_OPTION_ACTIONS),
|
|
378
|
+
injectedOptionActions.slice(MAX_INLINE_OPTION_ACTIONS),
|
|
379
|
+
],
|
|
380
|
+
[collapseOptionActions, injectedOptionActions]
|
|
381
|
+
);
|
|
382
|
+
const injectedOptionActionMenuItems = React.useMemo<IReqoreDropdownItem[]>(
|
|
383
|
+
() =>
|
|
384
|
+
menuOptionActions.map(
|
|
385
|
+
(action, index) =>
|
|
386
|
+
({
|
|
387
|
+
// A panel action labels itself with `label`, but an icon-only one
|
|
388
|
+
// (the IDE's AI-assist button) carries its name in the tooltip —
|
|
389
|
+
// a menu row has no hover affordance to fall back on.
|
|
390
|
+
label: action.label ?? action.tooltip ?? `Action ${index + 1}`,
|
|
391
|
+
icon: action.icon,
|
|
392
|
+
intent: action.intent,
|
|
393
|
+
disabled: action.disabled,
|
|
394
|
+
onClick: () => action.onClick?.(),
|
|
395
|
+
}) as IReqoreDropdownItem
|
|
396
|
+
),
|
|
397
|
+
[menuOptionActions]
|
|
398
|
+
);
|
|
399
|
+
const renderInjectedOptionAction = (
|
|
400
|
+
action: IReqorePanelAction,
|
|
401
|
+
index: number,
|
|
402
|
+
size: 'tiny' | 'small' = 'small'
|
|
403
|
+
) => {
|
|
404
|
+
// `show` drives visibility here instead of reaching the DOM. The classic
|
|
405
|
+
// path hands these to ReqorePanel, which honours `show: 'hover'` itself;
|
|
406
|
+
// the compact slots render plain buttons, so 'hover' becomes a CSS gate on
|
|
407
|
+
// the containing row/card (see compactRowStyles) — same config, same
|
|
408
|
+
// behaviour in both modes.
|
|
409
|
+
// `size` is destructured out and deliberately NOT honoured: the row owns
|
|
410
|
+
// its action strip's rhythm, and a consumer-supplied size made the
|
|
411
|
+
// injected button visibly smaller than the revert / more / confirm
|
|
412
|
+
// buttons beside it. The contextual `size` argument is the row's own
|
|
413
|
+
// (small when editing or in a card, tiny on a read row), so injected
|
|
414
|
+
// actions always match their neighbours.
|
|
415
|
+
const {
|
|
416
|
+
label: actionLabel,
|
|
417
|
+
onClick,
|
|
418
|
+
show,
|
|
419
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
420
|
+
size: _ignoredSize,
|
|
421
|
+
className,
|
|
422
|
+
...actionProps
|
|
423
|
+
} = action;
|
|
424
|
+
|
|
425
|
+
return (
|
|
426
|
+
<ReqoreButton
|
|
427
|
+
key={`${optionName}-injected-action-${index}`}
|
|
428
|
+
size={size}
|
|
429
|
+
minimal
|
|
430
|
+
flat
|
|
431
|
+
fixed
|
|
432
|
+
{...actionProps}
|
|
433
|
+
className={`${className ? `${className} ` : ''}options-injected-action${
|
|
434
|
+
show === 'hover' ? ' options-injected-action-hover' : ''
|
|
435
|
+
}`}
|
|
436
|
+
onClick={(event: React.MouseEvent<HTMLElement>) => {
|
|
437
|
+
event.stopPropagation();
|
|
438
|
+
onClick?.();
|
|
439
|
+
}}
|
|
440
|
+
>
|
|
441
|
+
{actionLabel}
|
|
442
|
+
</ReqoreButton>
|
|
443
|
+
);
|
|
444
|
+
};
|
|
341
445
|
const required = !!(schema?.required || schema?.required_groups);
|
|
342
446
|
const removable =
|
|
343
447
|
!readOnly && !schema?.preselected && !schema?.required && !schema?.required_groups;
|
|
@@ -675,6 +779,10 @@ export const CompactRow = memo(
|
|
|
675
779
|
} as IReqoreDropdownItem,
|
|
676
780
|
]
|
|
677
781
|
: []),
|
|
782
|
+
// Consumer-injected actions that did not fit inline (or collapsed
|
|
783
|
+
// wholesale on touch) land here — this row already has a menu, so they
|
|
784
|
+
// reuse it rather than adding a second one beside it.
|
|
785
|
+
...injectedOptionActionMenuItems,
|
|
678
786
|
]}
|
|
679
787
|
/>
|
|
680
788
|
);
|
|
@@ -748,6 +856,9 @@ export const CompactRow = memo(
|
|
|
748
856
|
message strip is visible. */}
|
|
749
857
|
{revertButton}
|
|
750
858
|
{clearValueButton}
|
|
859
|
+
{inlineOptionActions.map((action, index) =>
|
|
860
|
+
renderInjectedOptionAction(action, index)
|
|
861
|
+
)}
|
|
751
862
|
{moreMenu}
|
|
752
863
|
<ReqoreButton
|
|
753
864
|
className='options-readfirst-done'
|
|
@@ -902,6 +1013,9 @@ export const CompactRow = memo(
|
|
|
902
1013
|
</ReqoreButton>
|
|
903
1014
|
);
|
|
904
1015
|
})}
|
|
1016
|
+
{inlineOptionActions.map((action, index) =>
|
|
1017
|
+
renderInjectedOptionAction(action, index)
|
|
1018
|
+
)}
|
|
905
1019
|
{/* Clear-value sits before the More menu — the card analog of the
|
|
906
1020
|
inline row's Clear. Empties the value (keeps the field). */}
|
|
907
1021
|
{hasValue && !readOnly ?
|
|
@@ -1304,6 +1418,31 @@ export const CompactRow = memo(
|
|
|
1304
1418
|
{infoToggle}
|
|
1305
1419
|
</StyledActionSlot>
|
|
1306
1420
|
: null}
|
|
1421
|
+
{inlineOptionActions.map((action, index) =>
|
|
1422
|
+
renderInjectedOptionAction(action, index, 'tiny')
|
|
1423
|
+
)}
|
|
1424
|
+
{injectedOptionActionMenuItems.length ?
|
|
1425
|
+
<StyledActionSlot
|
|
1426
|
+
className='options-readfirst-actions-slot'
|
|
1427
|
+
$width={26}
|
|
1428
|
+
// The read row opens the editor when clicked. Without this the tap
|
|
1429
|
+
// that opens this menu also expands the row, which unmounts the
|
|
1430
|
+
// menu — on touch that made the collapsed actions unreachable,
|
|
1431
|
+
// the exact problem the collapse exists to solve.
|
|
1432
|
+
onClick={(event: React.MouseEvent<HTMLElement>) => event.stopPropagation()}
|
|
1433
|
+
>
|
|
1434
|
+
<ReqoreDropdown
|
|
1435
|
+
className='options-injected-actions-menu'
|
|
1436
|
+
icon='MoreFill'
|
|
1437
|
+
flat
|
|
1438
|
+
minimal
|
|
1439
|
+
fixed
|
|
1440
|
+
size='tiny'
|
|
1441
|
+
tooltip='Field actions'
|
|
1442
|
+
items={injectedOptionActionMenuItems}
|
|
1443
|
+
/>
|
|
1444
|
+
</StyledActionSlot>
|
|
1445
|
+
: null}
|
|
1307
1446
|
{/* The revert affordance lives in the status-dot column (a changed field
|
|
1308
1447
|
swaps its dot for the revert icon) so it sits at the same fixed x as
|
|
1309
1448
|
the dot — out of the value's way instead of floating over it. */}
|