@qoretechnologies/reqraft 0.10.51 → 0.10.52
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/expressions/ExpressionField.d.ts +4 -2
- package/dist/components/form/expressions/ExpressionField.d.ts.map +1 -1
- package/dist/components/form/expressions/ExpressionField.js +2 -2
- package/dist/components/form/expressions/ExpressionField.js.map +1 -1
- package/dist/components/form/expressions/builder/argumentWrapper.d.ts +13 -2
- package/dist/components/form/expressions/builder/argumentWrapper.d.ts.map +1 -1
- package/dist/components/form/expressions/builder/argumentWrapper.js +61 -3
- package/dist/components/form/expressions/builder/argumentWrapper.js.map +1 -1
- package/dist/components/form/expressions/builder/index.d.ts +4 -2
- package/dist/components/form/expressions/builder/index.d.ts.map +1 -1
- package/dist/components/form/expressions/builder/index.js +96 -15
- package/dist/components/form/expressions/builder/index.js.map +1 -1
- package/dist/components/form/expressions/builder/moveToPositionStrip.d.ts +19 -0
- package/dist/components/form/expressions/builder/moveToPositionStrip.d.ts.map +1 -0
- package/dist/components/form/expressions/builder/moveToPositionStrip.js +62 -0
- package/dist/components/form/expressions/builder/moveToPositionStrip.js.map +1 -0
- package/dist/components/form/expressions/mockExpressions.d.ts.map +1 -1
- package/dist/components/form/expressions/mockExpressions.js +18 -0
- package/dist/components/form/expressions/mockExpressions.js.map +1 -1
- package/dist/components/form/expressions/types.d.ts +8 -0
- package/dist/components/form/expressions/types.d.ts.map +1 -1
- package/dist/components/form/fields/schema-definition/CatalogNodeEditor.js +3 -2
- package/dist/components/form/fields/schema-definition/CatalogNodeEditor.js.map +1 -1
- package/dist/components/form/fields/schema-definition/MigrationsTab.js +3 -3
- package/dist/components/form/fields/schema-definition/MigrationsTab.js.map +1 -1
- package/dist/components/form/fields/schema-definition/helpers.d.ts +0 -2
- package/dist/components/form/fields/schema-definition/helpers.d.ts.map +1 -1
- package/dist/components/form/fields/schema-definition/helpers.js +1 -20
- package/dist/components/form/fields/schema-definition/helpers.js.map +1 -1
- package/dist/components/form/fields/template/TemplateField.d.ts +33 -4
- package/dist/components/form/fields/template/TemplateField.d.ts.map +1 -1
- package/dist/components/form/fields/template/TemplateField.js +57 -7
- package/dist/components/form/fields/template/TemplateField.js.map +1 -1
- package/dist/helpers/common.d.ts +4 -0
- package/dist/helpers/common.d.ts.map +1 -1
- package/dist/helpers/common.js +30 -1
- package/dist/helpers/common.js.map +1 -1
- package/package.json +1 -1
- package/src/components/form/expressions/ExpressionField.tsx +5 -1
- package/src/components/form/expressions/builder/ExpressionBuilder.stories.tsx +386 -0
- package/src/components/form/expressions/builder/argumentWrapper.tsx +137 -11
- package/src/components/form/expressions/builder/index.tsx +153 -5
- package/src/components/form/expressions/builder/moveToPositionStrip.tsx +156 -0
- package/src/components/form/expressions/mockExpressions.ts +18 -0
- package/src/components/form/expressions/types.ts +10 -0
- package/src/components/form/fields/schema-definition/CatalogNodeEditor.tsx +1 -1
- package/src/components/form/fields/schema-definition/MigrationsTab.tsx +1 -1
- package/src/components/form/fields/schema-definition/helpers.ts +0 -9
- package/src/components/form/fields/template/TemplateField.tsx +112 -4
- package/src/helpers/common.ts +31 -0
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
ReqoreDropdown,
|
|
10
10
|
ReqoreErrorBoundary,
|
|
11
11
|
ReqoreMenu,
|
|
12
|
+
ReqoreMenuItem,
|
|
12
13
|
ReqoreMenuSection,
|
|
13
14
|
ReqoreMessage,
|
|
14
15
|
ReqorePopover,
|
|
@@ -16,6 +17,8 @@ import {
|
|
|
16
17
|
} from '@qoretechnologies/reqore';
|
|
17
18
|
import { IReqoreButtonProps } from '@qoretechnologies/reqore/dist/components/Button';
|
|
18
19
|
import { IReqoreDropdownProps } from '@qoretechnologies/reqore/dist/components/Dropdown';
|
|
20
|
+
import { IReqoreMenuItemProps } from '@qoretechnologies/reqore/dist/components/Menu/item';
|
|
21
|
+
import { IReqoreIconName } from '@qoretechnologies/reqore/dist/types/icons';
|
|
19
22
|
import ReqoreMenuDivider, {
|
|
20
23
|
IReqoreMenuDividerProps,
|
|
21
24
|
} from '@qoretechnologies/reqore/dist/components/Menu/divider';
|
|
@@ -26,7 +29,7 @@ import {
|
|
|
26
29
|
} from '@qoretechnologies/reqore/dist/components/Textarea';
|
|
27
30
|
import { IQorusFormFieldSchemaBase, TQorusType } from '@qoretechnologies/ts-toolkit';
|
|
28
31
|
import { size } from 'lodash';
|
|
29
|
-
import { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
|
32
|
+
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
|
30
33
|
import { useUpdateEffect } from 'react-use';
|
|
31
34
|
import {
|
|
32
35
|
filterTemplatesByType as templatesFilterFunc,
|
|
@@ -44,7 +47,7 @@ import { ExpressionBuilder, IExpressionBuilderProps } from '../../expressions/bu
|
|
|
44
47
|
// Direct import — the cycle (TemplateField → ExpressionField → builder →
|
|
45
48
|
// TemplateField) is render-time only, safe like the other Field cycles.
|
|
46
49
|
import { ExpressionField } from '../../expressions/ExpressionField';
|
|
47
|
-
import { IExpression } from '../../expressions/types';
|
|
50
|
+
import { IExpression, TExpressionReorder } from '../../expressions/types';
|
|
48
51
|
import { useExpressions } from '../../expressions/useExpressions';
|
|
49
52
|
import { AutoFormField as Auto, IQorusType as IQorusFormType } from '../auto/AutoFormField';
|
|
50
53
|
import BooleanFormField from '../boolean/Boolean';
|
|
@@ -134,6 +137,14 @@ export interface ITemplateFieldProps extends Partial<
|
|
|
134
137
|
isDefaultFunction?: boolean;
|
|
135
138
|
isDefaultTemplate?: boolean;
|
|
136
139
|
menuItems?: TCustomTemplateItems;
|
|
140
|
+
/**
|
|
141
|
+
* SEAM (reqraft, additive): a collapsed section in the field's `⋮` menu,
|
|
142
|
+
* rendered before "Set Custom Value"; a row click closes the menu. The
|
|
143
|
+
* expression builder puts its operand reorder actions here.
|
|
144
|
+
*/
|
|
145
|
+
menuActions?: ITemplateMenuActions;
|
|
146
|
+
/** SEAM (reqraft, additive): forwarded to a nested expression builder. */
|
|
147
|
+
reorder?: TExpressionReorder;
|
|
137
148
|
/**
|
|
138
149
|
* SEAM (reqraft, additive): render expression mode through the
|
|
139
150
|
* `ExpressionField` shell — Visual (the ported builder) + Text (the
|
|
@@ -184,6 +195,92 @@ export type TCustomTemplateItems = (
|
|
|
184
195
|
| (IReqoreMenuDividerProps & { isDivider?: true })
|
|
185
196
|
)[];
|
|
186
197
|
|
|
198
|
+
/**
|
|
199
|
+
* The `menuActions` seam: a collapsed section of menu items, dividers, nested
|
|
200
|
+
* sections, or custom content — rendered with the popover's close callback so
|
|
201
|
+
* an inline control can shut the menu after acting.
|
|
202
|
+
*/
|
|
203
|
+
export interface ITemplateMenuActions {
|
|
204
|
+
label: string;
|
|
205
|
+
icon?: IReqoreIconName;
|
|
206
|
+
className?: string;
|
|
207
|
+
items: (
|
|
208
|
+
| IReqoreMenuItemProps
|
|
209
|
+
| (IReqoreMenuDividerProps & { isDivider: true })
|
|
210
|
+
| (ITemplateMenuActions & { isSection: true })
|
|
211
|
+
| { isCustom: true; content: (closePopover?: () => void) => React.ReactNode }
|
|
212
|
+
)[];
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const renderMenuActionRows = (
|
|
216
|
+
actions: ITemplateMenuActions,
|
|
217
|
+
closePopover: (() => void) | undefined,
|
|
218
|
+
size: IReqoreButtonProps['size']
|
|
219
|
+
): React.ReactNode =>
|
|
220
|
+
actions.items.map((item, index) => {
|
|
221
|
+
if ('isDivider' in item) {
|
|
222
|
+
return <ReqoreMenuDivider key={index} {...item} />;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if ('isCustom' in item) {
|
|
226
|
+
return <React.Fragment key={index}>{item.content(closePopover)}</React.Fragment>;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if ('isSection' in item) {
|
|
230
|
+
return (
|
|
231
|
+
<ReqoreMenuSection
|
|
232
|
+
key={index}
|
|
233
|
+
label={item.label}
|
|
234
|
+
icon={item.icon}
|
|
235
|
+
className={item.className}
|
|
236
|
+
isCollapsed
|
|
237
|
+
transparent
|
|
238
|
+
size={size}
|
|
239
|
+
>
|
|
240
|
+
{renderMenuActionRows(item, closePopover, size)}
|
|
241
|
+
</ReqoreMenuSection>
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return (
|
|
246
|
+
<ReqoreMenuItem
|
|
247
|
+
{...item}
|
|
248
|
+
key={index}
|
|
249
|
+
onClick={(event, itemId) => {
|
|
250
|
+
item.onClick?.(event, itemId, closePopover);
|
|
251
|
+
closePopover?.();
|
|
252
|
+
}}
|
|
253
|
+
/>
|
|
254
|
+
);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// A direct child of `ReqoreMenu`, like `CustomMenuItems`, so the menu hands it
|
|
258
|
+
// the popover's `closePopover` — a section does not pass it on to its rows.
|
|
259
|
+
const MenuActionsSection = memo(
|
|
260
|
+
({
|
|
261
|
+
actions,
|
|
262
|
+
closePopover,
|
|
263
|
+
size,
|
|
264
|
+
...rest
|
|
265
|
+
}: {
|
|
266
|
+
actions: ITemplateMenuActions;
|
|
267
|
+
closePopover?: () => void;
|
|
268
|
+
size?: IReqoreButtonProps['size'];
|
|
269
|
+
}) => (
|
|
270
|
+
<ReqoreMenuSection
|
|
271
|
+
label={actions.label}
|
|
272
|
+
icon={actions.icon}
|
|
273
|
+
isCollapsed
|
|
274
|
+
transparent
|
|
275
|
+
className='template-menu-actions'
|
|
276
|
+
size={size}
|
|
277
|
+
{...rest}
|
|
278
|
+
>
|
|
279
|
+
{renderMenuActionRows(actions, closePopover, size)}
|
|
280
|
+
</ReqoreMenuSection>
|
|
281
|
+
)
|
|
282
|
+
);
|
|
283
|
+
|
|
187
284
|
export const CustomMenuItems = memo(
|
|
188
285
|
({
|
|
189
286
|
items,
|
|
@@ -317,6 +414,8 @@ export const TemplateField = memo(
|
|
|
317
414
|
level,
|
|
318
415
|
className,
|
|
319
416
|
menuItems,
|
|
417
|
+
menuActions,
|
|
418
|
+
reorder,
|
|
320
419
|
label,
|
|
321
420
|
...rest
|
|
322
421
|
}: ITemplateFieldProps) => {
|
|
@@ -579,6 +678,8 @@ export const TemplateField = memo(
|
|
|
579
678
|
const showFunctionsDropdown =
|
|
580
679
|
allowFunctions && !hasOnlyAllowedValues && !rest.readonly && !internalIsFunction;
|
|
581
680
|
const showTemplatesButton = showTemplateToggle && !isTemplate;
|
|
681
|
+
// The "Set value" label promises a way to set one — reorder rows alone don't.
|
|
682
|
+
const hasValueRows = showFunctionsDropdown || showTemplatesButton || size(menuItems) > 0;
|
|
582
683
|
|
|
583
684
|
if (hasOnlyExpressions) {
|
|
584
685
|
return showFunctionsDropdown ? (
|
|
@@ -609,7 +710,7 @@ export const TemplateField = memo(
|
|
|
609
710
|
) : null;
|
|
610
711
|
}
|
|
611
712
|
|
|
612
|
-
if (
|
|
713
|
+
if (hasValueRows || size(menuActions?.items) > 0) {
|
|
613
714
|
return (
|
|
614
715
|
<ReqorePopover
|
|
615
716
|
component={ReqoreButton}
|
|
@@ -631,7 +732,7 @@ export const TemplateField = memo(
|
|
|
631
732
|
// sibling action buttons (reqore alignSelf; replaces a reqraft
|
|
632
733
|
// `align-self !important` override of this button).
|
|
633
734
|
alignSelf: 'center',
|
|
634
|
-
label: hasInputAffordance ? undefined : 'Set value',
|
|
735
|
+
label: hasInputAffordance || !hasValueRows ? undefined : 'Set value',
|
|
635
736
|
style:
|
|
636
737
|
hasInputAffordance ?
|
|
637
738
|
{
|
|
@@ -687,6 +788,10 @@ export const TemplateField = memo(
|
|
|
687
788
|
</ReqoreButton>
|
|
688
789
|
) : null}
|
|
689
790
|
|
|
791
|
+
{size(menuActions?.items) > 0 ? (
|
|
792
|
+
<MenuActionsSection actions={menuActions} size={rest.size} />
|
|
793
|
+
) : null}
|
|
794
|
+
|
|
690
795
|
{size(menuItems) > 0 ? (
|
|
691
796
|
<CustomMenuItems
|
|
692
797
|
items={menuItems}
|
|
@@ -715,6 +820,7 @@ export const TemplateField = memo(
|
|
|
715
820
|
type,
|
|
716
821
|
value,
|
|
717
822
|
menuItems,
|
|
823
|
+
menuActions,
|
|
718
824
|
internalIsFunction,
|
|
719
825
|
hasInputAffordance,
|
|
720
826
|
]);
|
|
@@ -758,6 +864,7 @@ export const TemplateField = memo(
|
|
|
758
864
|
serverHandled={rest.server_expression_handling}
|
|
759
865
|
extraActions={extraActions}
|
|
760
866
|
size={rest.size}
|
|
867
|
+
reorder={reorder}
|
|
761
868
|
/>
|
|
762
869
|
</ReqoreErrorBoundary>
|
|
763
870
|
{renderControls()}
|
|
@@ -783,6 +890,7 @@ export const TemplateField = memo(
|
|
|
783
890
|
expressionsUrl={rest.expressions_url}
|
|
784
891
|
serverHandled={rest.server_expression_handling}
|
|
785
892
|
extraActions={extraActions}
|
|
893
|
+
reorder={reorder}
|
|
786
894
|
/>
|
|
787
895
|
</ReqoreErrorBoundary>
|
|
788
896
|
{renderControls()}
|
package/src/helpers/common.ts
CHANGED
|
@@ -275,3 +275,34 @@ export const getAddress = (v?: string): string => {
|
|
|
275
275
|
// We need to join back the rest of the address in case there were :// in it
|
|
276
276
|
return valueList.slice(1).join('://');
|
|
277
277
|
};
|
|
278
|
+
|
|
279
|
+
// ─── List helpers ─────────────────────────────────────────────────────────────
|
|
280
|
+
|
|
281
|
+
/** Immutably moves a list element from `from` to `to`. */
|
|
282
|
+
export const moveItem = <T>(list: T[], from: number, to: number): T[] => {
|
|
283
|
+
if (from === to || from < 0 || to < 0 || from >= list.length) return list;
|
|
284
|
+
const next = [...list];
|
|
285
|
+
const [item] = next.splice(from, 1);
|
|
286
|
+
next.splice(Math.min(to, next.length), 0, item);
|
|
287
|
+
return next;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
/** `1` → `1st`, `2` → `2nd`, `11` → `11th`. */
|
|
291
|
+
export const ordinal = (n: number): string => {
|
|
292
|
+
const mod100 = n % 100;
|
|
293
|
+
|
|
294
|
+
if (mod100 >= 11 && mod100 <= 13) {
|
|
295
|
+
return `${n}th`;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
switch (n % 10) {
|
|
299
|
+
case 1:
|
|
300
|
+
return `${n}st`;
|
|
301
|
+
case 2:
|
|
302
|
+
return `${n}nd`;
|
|
303
|
+
case 3:
|
|
304
|
+
return `${n}rd`;
|
|
305
|
+
default:
|
|
306
|
+
return `${n}th`;
|
|
307
|
+
}
|
|
308
|
+
};
|