@qoretechnologies/reqraft 0.10.13 → 0.10.14

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.
@@ -21,13 +21,13 @@ import {
21
21
  } from '@qoretechnologies/reqore/dist/components/Panel';
22
22
  import { IReqoreFormTemplates } from '@qoretechnologies/reqore/dist/components/Textarea';
23
23
  import { TReqoreIntent } from '@qoretechnologies/reqore/dist/constants/theme';
24
- import { IReqoreIconName } from '@qoretechnologies/reqore/dist/types/icons';
25
24
  import {
26
25
  changeDarkness,
27
26
  getMainBackgroundColor,
28
27
  getReadableColor,
29
28
  percentToHexAlpha,
30
29
  } from '@qoretechnologies/reqore/dist/helpers/colors';
30
+ import { IReqoreIconName } from '@qoretechnologies/reqore/dist/types/icons';
31
31
  import {
32
32
  IQorusFormField,
33
33
  IQorusFormFieldMessage,
@@ -48,11 +48,10 @@ import reduce from 'lodash/reduce';
48
48
  import size from 'lodash/size';
49
49
  import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
50
50
  import { useMeasure, useMount, useUpdateEffect } from 'react-use';
51
- import { createContext } from 'use-context-selector';
52
51
  import styled from 'styled-components';
52
+ import { createContext } from 'use-context-selector';
53
53
  import { getDefaultValue, insertAtIndex, richtextToString } from '../../../helpers/common';
54
54
  import { getRequiredOptionMessage } from '../../../helpers/options';
55
- import { query } from '../../../utils/fetch';
56
55
  import {
57
56
  IValidationResult,
58
57
  hasAllDependenciesFullfilled,
@@ -61,6 +60,7 @@ import {
61
60
  } from '../../../helpers/validations';
62
61
  import { useQorusTypes } from '../../../hooks/useQorusTypes';
63
62
  import { useTemplates } from '../../../hooks/useTemplates';
63
+ import { query } from '../../../utils/fetch';
64
64
  import { Description } from '../../Description';
65
65
  import { FocusedEditing } from '../../FocusedEditing';
66
66
  import { SelectFormField } from '../fields/select/Select';
@@ -72,12 +72,6 @@ import {
72
72
  } from '../fields/template/TemplateField';
73
73
  import { CompactRow } from './CompactRow';
74
74
  import { CompactRowContext, ICompactRowContext } from './compactRowContext';
75
- import { CompactToolbar } from './CompactToolbar';
76
- import {
77
- CompactToolbarContext,
78
- ICompactToolbarContext,
79
- TCompactSort,
80
- } from './compactToolbarContext';
81
75
  import {
82
76
  GROUP_INDENT,
83
77
  LABEL_COL_MAX,
@@ -91,9 +85,16 @@ import {
91
85
  StyledStatusBox,
92
86
  StyledStatusBoxGroupLabel,
93
87
  } from './compactRowStyles';
88
+ import { CompactToolbar } from './CompactToolbar';
89
+ import {
90
+ CompactToolbarContext,
91
+ ICompactToolbarContext,
92
+ TCompactSort,
93
+ } from './compactToolbarContext';
94
94
  import { OptionFieldMessages } from './OptionFieldMessages';
95
95
  import { OptionsHelpDialog } from './OptionsHelpDialog';
96
96
  import {
97
+ TReadFirstStatus,
97
98
  getFirstAttentionOptionName,
98
99
  getOptionGroup,
99
100
  getOptionGroupLabel,
@@ -101,7 +102,6 @@ import {
101
102
  getReadFirstCompletion,
102
103
  getReadFirstStatus,
103
104
  isOptionValueEmpty,
104
- TReadFirstStatus,
105
105
  } from './readFirst';
106
106
 
107
107
  // Re-export types for consumers
@@ -201,13 +201,6 @@ const StyledCompactWrap = styled.div<{ $flush?: boolean }>`
201
201
  engage instead of overflowing the container horizontally. */
202
202
  min-width: 0;
203
203
  max-width: 100%;
204
- /* A bit of horizontal breathing room for the whole form (header + content
205
- alike). Horizontal only — top padding would break the sticky toolbar's
206
- flush pin (see the scroll-context note below). Dropped to flush via the
207
- compactFlush prop, for embeds that own their own gutters (e.g. the
208
- SchemaDefinition tab body). */
209
- padding: ${({ $flush }) => ($flush ? '0' : '0 12px')};
210
-
211
204
  /* Own our scroll context instead of borrowing the host's. The sticky toolbar
212
205
  pins to whatever scrolls; if that scroller carries top padding (e.g. a
213
206
  ReqorePanel/ReqoreContent body), sticky \`top: 0\` resolves against its
@@ -525,6 +518,18 @@ export interface IFormEngineProps extends Omit<IReqoreCollectionProps, 'onChange
525
518
  * transparently inside the parent's edit card. Default `false`.
526
519
  */
527
520
  compactNested?: boolean;
521
+ /**
522
+ * Compact mode only: props forwarded to the read-first form's outer
523
+ * `ReqorePanel` — the panel that carries the sticky toolbar header and holds
524
+ * the status boxes. Spread AFTER the engine's own defaults, so anything set
525
+ * here wins (`flat`, `raised`, `minimal`, `stickyHeader`, `label`, `icon`,
526
+ * `intent`, `padded`, `size`, …). Two props merge instead of replacing, so a
527
+ * consumer can add to the panel without dismantling the form:
528
+ * - `actions` — appended after the engine's toolbar action.
529
+ * - `contentStyle` — merged over the engine's flex-column layout.
530
+ * No-op in classic (non-compact) mode.
531
+ */
532
+ compactPanelProps?: IReqorePanelProps;
528
533
  /** Compact mode only: per-group display metadata (label / icon / subtitle /
529
534
  * order) — the server only sends the bare group key. */
530
535
  groups?: Record<string, IFormEngineGroup>;
@@ -609,6 +614,7 @@ export const FormEngine = ({
609
614
  compact,
610
615
  compactFlush = false,
611
616
  compactNested = false,
617
+ compactPanelProps,
612
618
  commitMode = 'immediate',
613
619
  expandMode = 'single',
614
620
  onCommit,
@@ -1709,8 +1715,13 @@ export const FormEngine = ({
1709
1715
  <>
1710
1716
  {(() => {
1711
1717
  const schemaMsgs = (
1712
- suppressSchemaMessages ? [] : (options?.[optionName] as any)?.messages || []
1713
- ) as { intent?: string; title?: string; content?: string }[];
1718
+ suppressSchemaMessages ?
1719
+ []
1720
+ : (options?.[optionName] as any)?.messages || []) as {
1721
+ intent?: string;
1722
+ title?: string;
1723
+ content?: string;
1724
+ }[];
1714
1725
  if (!schemaMsgs.length) return null;
1715
1726
  const items = schemaMsgs.map(({ intent, title, content }, index) => (
1716
1727
  <ReqoreMessage
@@ -2114,7 +2125,13 @@ export const FormEngine = ({
2114
2125
  ]
2115
2126
  );
2116
2127
 
2117
- const compactHeaderActions = useMemo(() => [{ as: CompactToolbar, responsive: false }], []);
2128
+ // The engine's own toolbar action, plus whatever the consumer added through
2129
+ // `compactPanelProps.actions` — appended, so an outside action can never
2130
+ // knock the form's toolbar out of the header.
2131
+ const compactHeaderActions = useMemo(
2132
+ () => [{ as: CompactToolbar, responsive: false }, ...(compactPanelProps?.actions || [])],
2133
+ [compactPanelProps?.actions]
2134
+ );
2118
2135
  const renderCompact = () => {
2119
2136
  const headerBg = `${changeDarkness(getMainBackgroundColor(theme), 0.02)}${percentToHexAlpha(88)}`;
2120
2137
  // Toolbar filters narrow the listed rows; the meter reflects the full set.
@@ -2357,22 +2374,24 @@ export const FormEngine = ({
2357
2374
  $headerBg={compactNested ? 'transparent' : headerBg}
2358
2375
  $nested={compactNested}
2359
2376
  flat
2377
+ raised
2378
+ minimal
2360
2379
  // No panel background: the form sits transparently on whatever
2361
2380
  // hosts it (page, drawer, or — for an arg_schema field — the
2362
2381
  // parent's edit card) instead of stacking its own dark surface.
2363
2382
  // The status boxes keep their own tints; the sticky toolbar keeps
2364
2383
  // its blurred header via the $headerBg override.
2365
- transparent
2366
2384
  stickyHeader={!compactNested}
2367
- padded={false}
2385
+ // Consumer overrides land last so they win over every default
2386
+ // above; `actions` and `contentStyle` below merge rather than
2387
+ // replace (see `compactPanelProps`).
2388
+ {...compactPanelProps}
2368
2389
  actions={compactHeaderActions}
2369
2390
  contentStyle={{
2370
2391
  display: 'flex',
2371
2392
  flexFlow: 'column',
2372
2393
  gap: '10px',
2373
- // Nested sub-form: no surrounding panel padding (it's flush in
2374
- // the parent card); top-level keeps a small bottom gutter.
2375
- padding: compactNested ? '0' : '0 0 12px',
2394
+ ...compactPanelProps?.contentStyle,
2376
2395
  }}
2377
2396
  >
2378
2397
  {size(groupKeys) === 0 ?
@@ -47,14 +47,13 @@ export const StyledCompactPanel = styled(ReqorePanel)<{
47
47
  $nested?: boolean;
48
48
  }>`
49
49
  > .reqore-panel-title {
50
- background: ${({ $headerBg }) => $headerBg};
51
50
  /* The blur + translateZ exist only to make the STICKY top-level toolbar ghost
52
51
  content beneath it; a nested sub-form's header isn't sticky, so skip them
53
52
  (and the stacking context translateZ creates). */
54
53
  ${({ $nested }) =>
55
- $nested ?
56
- ''
57
- : 'backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); transform: translateZ(0);'}
54
+ $nested ? '' : (
55
+ 'backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); transform: translateZ(0);'
56
+ )}
58
57
  padding-top: ${GAP_FROM_SIZE[HEADER_GAP]}px;
59
58
  padding-bottom: ${GAP_FROM_SIZE[HEADER_GAP]}px;
60
59
  }
@@ -625,5 +624,4 @@ export const StyledGroupBody = styled.div<{
625
624
  padding-top: 0;
626
625
  padding-bottom: 0;
627
626
  }
628
-
629
627
  `;