@qoretechnologies/reqraft 0.10.55-pr.124.g43fa138 → 0.10.55
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/.claude/CLAUDE.md +25 -0
- package/.tasks/INDEX.md +1 -0
- package/.tasks/STORY_NETWORK_ISOLATION.md +98 -0
- package/README.md +1 -1
- package/design/FORM_ENGINE_COMPACT.md +34 -0
- package/design/FORM_ENGINE_EXPRESSIONS.md +110 -0
- package/design/FORM_ENGINE_FIELD_MIGRATION.md +155 -1
- package/design/IDE_INTEGRATION.md +13 -0
- package/design/RENDER_EXPRESSION_TRANSPORT.md +76 -10
- package/design/SELECT_DIALOG_FLOOR.md +86 -0
- package/design/SMART_EDITOR_UX.md +21 -0
- package/design/UNAVAILABLE_ALLOWED_VALUES.md +226 -0
- package/dist/components/composer/Composer.d.ts +8 -3
- package/dist/components/composer/Composer.d.ts.map +1 -1
- package/dist/components/composer/Composer.js.map +1 -1
- package/dist/components/dpqlEditor/DpqlEditor.d.ts.map +1 -1
- package/dist/components/dpqlEditor/DpqlEditor.js +3 -3
- package/dist/components/dpqlEditor/DpqlEditor.js.map +1 -1
- package/dist/components/dpqlEditor/dpqlHelpers.d.ts +6 -0
- package/dist/components/dpqlEditor/dpqlHelpers.d.ts.map +1 -1
- package/dist/components/dpqlEditor/dpqlHelpers.js +21 -2
- package/dist/components/dpqlEditor/dpqlHelpers.js.map +1 -1
- package/dist/components/dpqlEditor/dpqlProbe.d.ts +37 -0
- package/dist/components/dpqlEditor/dpqlProbe.d.ts.map +1 -0
- package/dist/components/dpqlEditor/dpqlProbe.js +203 -0
- package/dist/components/dpqlEditor/dpqlProbe.js.map +1 -0
- package/dist/components/dpqlEditor/dpqlTags.d.ts +8 -0
- package/dist/components/dpqlEditor/dpqlTags.d.ts.map +1 -1
- package/dist/components/dpqlEditor/dpqlTags.js +5 -1
- package/dist/components/dpqlEditor/dpqlTags.js.map +1 -1
- package/dist/components/dpqlEditor/index.d.ts +4 -0
- package/dist/components/dpqlEditor/index.d.ts.map +1 -1
- package/dist/components/dpqlEditor/index.js +5 -1
- package/dist/components/dpqlEditor/index.js.map +1 -1
- package/dist/components/dpqlEditor/types.d.ts +42 -2
- package/dist/components/dpqlEditor/types.d.ts.map +1 -1
- package/dist/components/dpqlEditor/types.js +0 -4
- package/dist/components/dpqlEditor/types.js.map +1 -1
- package/dist/components/dpqlEditor/useDpqlProbe.d.ts +4 -0
- package/dist/components/dpqlEditor/useDpqlProbe.d.ts.map +1 -0
- package/dist/components/dpqlEditor/useDpqlProbe.js +29 -0
- package/dist/components/dpqlEditor/useDpqlProbe.js.map +1 -0
- package/dist/components/dpqlEditor/useDpqlSession.d.ts +5 -2
- package/dist/components/dpqlEditor/useDpqlSession.d.ts.map +1 -1
- package/dist/components/dpqlEditor/useDpqlSession.js +8 -2
- package/dist/components/dpqlEditor/useDpqlSession.js.map +1 -1
- package/dist/components/form/engine/CompactRow.d.ts.map +1 -1
- package/dist/components/form/engine/CompactRow.js +414 -128
- 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 +5 -2
- package/dist/components/form/engine/CompactToolbar.js.map +1 -1
- package/dist/components/form/engine/FormEngine.d.ts +273 -22
- package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
- package/dist/components/form/engine/FormEngine.js +669 -192
- package/dist/components/form/engine/FormEngine.js.map +1 -1
- package/dist/components/form/engine/FormFieldsSkeleton.d.ts +48 -0
- package/dist/components/form/engine/FormFieldsSkeleton.d.ts.map +1 -0
- package/dist/components/form/engine/FormFieldsSkeleton.js +41 -0
- package/dist/components/form/engine/FormFieldsSkeleton.js.map +1 -0
- package/dist/components/form/engine/OptionFieldMessages.d.ts +108 -2
- package/dist/components/form/engine/OptionFieldMessages.d.ts.map +1 -1
- package/dist/components/form/engine/OptionFieldMessages.js +203 -13
- 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 +68 -5
- package/dist/components/form/engine/_structuredData/SchemaDataView.js.map +1 -1
- package/dist/components/form/engine/compactRowContext.d.ts +15 -1
- 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 +55 -29
- package/dist/components/form/engine/compactRowStyles.js.map +1 -1
- package/dist/components/form/engine/compactToolbarContext.d.ts +1 -0
- package/dist/components/form/engine/compactToolbarContext.d.ts.map +1 -1
- package/dist/components/form/engine/optionActions.d.ts +37 -1
- package/dist/components/form/engine/optionActions.d.ts.map +1 -1
- package/dist/components/form/engine/optionActions.js +71 -1
- package/dist/components/form/engine/optionActions.js.map +1 -1
- package/dist/components/form/engine/optionsContext.d.ts +22 -0
- package/dist/components/form/engine/optionsContext.d.ts.map +1 -0
- package/dist/components/form/engine/optionsContext.js +20 -0
- package/dist/components/form/engine/optionsContext.js.map +1 -0
- package/dist/components/form/engine/readFirst.d.ts +42 -1
- package/dist/components/form/engine/readFirst.d.ts.map +1 -1
- package/dist/components/form/engine/readFirst.js +76 -8
- package/dist/components/form/engine/readFirst.js.map +1 -1
- package/dist/components/form/engine/rendererTypes.d.ts +42 -3
- package/dist/components/form/engine/rendererTypes.d.ts.map +1 -1
- package/dist/components/form/engine/rendererTypes.js +3 -1
- package/dist/components/form/engine/rendererTypes.js.map +1 -1
- package/dist/components/form/engine/rowFocus.d.ts +30 -0
- package/dist/components/form/engine/rowFocus.d.ts.map +1 -0
- package/dist/components/form/engine/rowFocus.js +93 -0
- package/dist/components/form/engine/rowFocus.js.map +1 -0
- package/dist/components/form/engine/rowMenuContext.d.ts +78 -0
- package/dist/components/form/engine/rowMenuContext.d.ts.map +1 -0
- package/dist/components/form/engine/rowMenuContext.js +103 -0
- package/dist/components/form/engine/rowMenuContext.js.map +1 -0
- package/dist/components/form/engine/rowOpenPicker.d.ts +27 -0
- package/dist/components/form/engine/rowOpenPicker.d.ts.map +1 -0
- package/dist/components/form/engine/rowOpenPicker.js +30 -0
- package/dist/components/form/engine/rowOpenPicker.js.map +1 -0
- package/dist/components/form/engine/typeChoices.d.ts +42 -0
- package/dist/components/form/engine/typeChoices.d.ts.map +1 -0
- package/dist/components/form/engine/typeChoices.js +33 -0
- package/dist/components/form/engine/typeChoices.js.map +1 -0
- package/dist/components/form/expressions/DpqlRendering.d.ts +26 -0
- package/dist/components/form/expressions/DpqlRendering.d.ts.map +1 -0
- package/dist/components/form/expressions/DpqlRendering.js +53 -0
- package/dist/components/form/expressions/DpqlRendering.js.map +1 -0
- package/dist/components/form/expressions/ExpressionField.d.ts +7 -1
- package/dist/components/form/expressions/ExpressionField.d.ts.map +1 -1
- package/dist/components/form/expressions/ExpressionField.js +203 -45
- package/dist/components/form/expressions/ExpressionField.js.map +1 -1
- package/dist/components/form/expressions/argumentPresence.d.ts +84 -0
- package/dist/components/form/expressions/argumentPresence.d.ts.map +1 -0
- package/dist/components/form/expressions/argumentPresence.js +217 -0
- package/dist/components/form/expressions/argumentPresence.js.map +1 -0
- package/dist/components/form/expressions/builder/argumentLabel.d.ts.map +1 -1
- package/dist/components/form/expressions/builder/argumentLabel.js +9 -4
- package/dist/components/form/expressions/builder/argumentLabel.js.map +1 -1
- package/dist/components/form/expressions/builder/index.d.ts +15 -2
- package/dist/components/form/expressions/builder/index.d.ts.map +1 -1
- package/dist/components/form/expressions/builder/index.js +21 -65
- package/dist/components/form/expressions/builder/index.js.map +1 -1
- package/dist/components/form/expressions/builder/renderTemplate.d.ts +4 -1
- package/dist/components/form/expressions/builder/renderTemplate.d.ts.map +1 -1
- package/dist/components/form/expressions/builder/renderTemplate.js +10 -67
- package/dist/components/form/expressions/builder/renderTemplate.js.map +1 -1
- package/dist/components/form/expressions/mockExpressions.d.ts.map +1 -1
- package/dist/components/form/expressions/mockExpressions.js +8 -4
- package/dist/components/form/expressions/mockExpressions.js.map +1 -1
- package/dist/components/form/expressions/renderExpressionToText.d.ts +1 -1
- package/dist/components/form/expressions/renderExpressionToText.d.ts.map +1 -1
- package/dist/components/form/expressions/renderExpressionToText.js +95 -19
- package/dist/components/form/expressions/renderExpressionToText.js.map +1 -1
- package/dist/components/form/expressions/types.d.ts +17 -2
- package/dist/components/form/expressions/types.d.ts.map +1 -1
- package/dist/components/form/expressions/useExpressions.d.ts.map +1 -1
- package/dist/components/form/expressions/useExpressions.js +5 -2
- package/dist/components/form/expressions/useExpressions.js.map +1 -1
- package/dist/components/form/expressions/useRenderExpression.d.ts +7 -16
- package/dist/components/form/expressions/useRenderExpression.d.ts.map +1 -1
- package/dist/components/form/expressions/useRenderExpression.js +50 -126
- package/dist/components/form/expressions/useRenderExpression.js.map +1 -1
- package/dist/components/form/fields/Field.d.ts +21 -0
- package/dist/components/form/fields/Field.d.ts.map +1 -1
- package/dist/components/form/fields/Field.js +54 -8
- package/dist/components/form/fields/Field.js.map +1 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.d.ts +11 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.d.ts.map +1 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.js +52 -8
- package/dist/components/form/fields/allowed-values/AllowedValues.js.map +1 -1
- package/dist/components/form/fields/auto/AutoFormField.d.ts +7 -1
- package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
- package/dist/components/form/fields/auto/AutoFormField.js +91 -28
- package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
- package/dist/components/form/fields/date/Date.d.ts +1 -1
- package/dist/components/form/fields/date/Date.d.ts.map +1 -1
- package/dist/components/form/fields/date/Date.js +16 -2
- package/dist/components/form/fields/date/Date.js.map +1 -1
- package/dist/components/form/fields/long-string/LongString.d.ts.map +1 -1
- package/dist/components/form/fields/long-string/LongString.js +14 -2
- package/dist/components/form/fields/long-string/LongString.js.map +1 -1
- package/dist/components/form/fields/multi-select/MultiSelectFormField.d.ts.map +1 -1
- package/dist/components/form/fields/multi-select/MultiSelectFormField.js +50 -4
- package/dist/components/form/fields/multi-select/MultiSelectFormField.js.map +1 -1
- package/dist/components/form/fields/number/Number.d.ts +12 -1
- package/dist/components/form/fields/number/Number.d.ts.map +1 -1
- package/dist/components/form/fields/number/Number.js +6 -3
- package/dist/components/form/fields/number/Number.js.map +1 -1
- package/dist/components/form/fields/rich-text/RichText.d.ts +47 -2
- package/dist/components/form/fields/rich-text/RichText.d.ts.map +1 -1
- package/dist/components/form/fields/rich-text/RichText.js +153 -12
- package/dist/components/form/fields/rich-text/RichText.js.map +1 -1
- package/dist/components/form/fields/select/Select.d.ts.map +1 -1
- package/dist/components/form/fields/select/Select.js +120 -20
- package/dist/components/form/fields/select/Select.js.map +1 -1
- package/dist/components/form/fields/select/SelectCollection.d.ts +166 -9
- package/dist/components/form/fields/select/SelectCollection.d.ts.map +1 -1
- package/dist/components/form/fields/select/SelectCollection.js +200 -7
- package/dist/components/form/fields/select/SelectCollection.js.map +1 -1
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.d.ts +2 -1
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.d.ts.map +1 -1
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.js +3 -2
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.js.map +1 -1
- package/dist/components/form/fields/template/TemplateField.d.ts +34 -2
- package/dist/components/form/fields/template/TemplateField.d.ts.map +1 -1
- package/dist/components/form/fields/template/TemplateField.js +606 -58
- package/dist/components/form/fields/template/TemplateField.js.map +1 -1
- package/dist/components/form/fields/template/TemplateText.d.ts +36 -0
- package/dist/components/form/fields/template/TemplateText.d.ts.map +1 -0
- package/dist/components/form/fields/template/TemplateText.js +80 -0
- package/dist/components/form/fields/template/TemplateText.js.map +1 -0
- 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 +4 -0
- package/dist/components/form/index.js.map +1 -1
- package/dist/components/smartEditor/SmartEditor.d.ts.map +1 -1
- package/dist/components/smartEditor/SmartEditor.js +29 -8
- package/dist/components/smartEditor/SmartEditor.js.map +1 -1
- package/dist/components/smartEditor/useLspSession.d.ts +5 -1
- package/dist/components/smartEditor/useLspSession.d.ts.map +1 -1
- package/dist/components/smartEditor/useLspSession.js +16 -2
- package/dist/components/smartEditor/useLspSession.js.map +1 -1
- package/dist/components/supportTicket/TicketReplyBox.d.ts +8 -4
- package/dist/components/supportTicket/TicketReplyBox.d.ts.map +1 -1
- package/dist/components/supportTicket/TicketReplyBox.js.map +1 -1
- package/dist/helpers/common.d.ts.map +1 -1
- package/dist/helpers/common.js +7 -3
- package/dist/helpers/common.js.map +1 -1
- package/dist/helpers/dpqlDetection.d.ts +58 -0
- package/dist/helpers/dpqlDetection.d.ts.map +1 -0
- package/dist/helpers/dpqlDetection.js +164 -0
- package/dist/helpers/dpqlDetection.js.map +1 -0
- package/dist/helpers/optionUiTypes.d.ts +31 -3
- package/dist/helpers/optionUiTypes.d.ts.map +1 -1
- package/dist/helpers/optionUiTypes.js +36 -1
- package/dist/helpers/optionUiTypes.js.map +1 -1
- package/dist/helpers/options.d.ts +57 -0
- package/dist/helpers/options.d.ts.map +1 -1
- package/dist/helpers/options.js +97 -1
- package/dist/helpers/options.js.map +1 -1
- package/dist/helpers/templateItems.d.ts +47 -0
- package/dist/helpers/templateItems.d.ts.map +1 -0
- package/dist/helpers/templateItems.js +88 -0
- package/dist/helpers/templateItems.js.map +1 -0
- package/dist/helpers/templateText.d.ts +80 -0
- package/dist/helpers/templateText.d.ts.map +1 -0
- package/dist/helpers/templateText.js +291 -0
- package/dist/helpers/templateText.js.map +1 -0
- package/dist/helpers/templates.d.ts +30 -12
- package/dist/helpers/templates.d.ts.map +1 -1
- package/dist/helpers/templates.js +91 -33
- package/dist/helpers/templates.js.map +1 -1
- package/dist/helpers/validations.d.ts +35 -8
- package/dist/helpers/validations.d.ts.map +1 -1
- package/dist/helpers/validations.js +162 -25
- package/dist/helpers/validations.js.map +1 -1
- package/dist/hooks/useArgSchema.d.ts +2 -1
- package/dist/hooks/useArgSchema.d.ts.map +1 -1
- package/dist/hooks/useFetch/useFetch.d.ts +3 -1
- package/dist/hooks/useFetch/useFetch.d.ts.map +1 -1
- package/dist/hooks/useFetch/useFetch.js +47 -9
- package/dist/hooks/useFetch/useFetch.js.map +1 -1
- package/dist/hooks/useTemplates.d.ts +20 -0
- package/dist/hooks/useTemplates.d.ts.map +1 -1
- package/dist/hooks/useTemplates.js +34 -2
- package/dist/hooks/useTemplates.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/fetch.d.ts +151 -1
- package/dist/utils/fetch.d.ts.map +1 -1
- package/dist/utils/fetch.js +256 -44
- package/dist/utils/fetch.js.map +1 -1
- package/dist/utils/lspClient.d.ts +6 -0
- package/dist/utils/lspClient.d.ts.map +1 -1
- package/dist/utils/lspClient.js +62 -11
- package/dist/utils/lspClient.js.map +1 -1
- package/dist/utils/websocket.d.ts +6 -0
- package/dist/utils/websocket.d.ts.map +1 -1
- package/dist/utils/websocket.js +15 -7
- package/dist/utils/websocket.js.map +1 -1
- package/package.json +10 -6
- package/src/components/composer/Composer.tsx +7 -2
- package/src/components/dpqlEditor/DpqlEditor.stories.tsx +3 -119
- package/src/components/dpqlEditor/DpqlEditor.tsx +5 -2
- package/src/components/dpqlEditor/dpqlHelpers.ts +20 -1
- package/src/components/dpqlEditor/dpqlProbe.ts +165 -0
- package/src/components/dpqlEditor/dpqlTags.ts +13 -0
- package/src/components/dpqlEditor/index.ts +4 -0
- package/src/components/dpqlEditor/types.ts +38 -2
- package/src/components/dpqlEditor/useDpqlProbe.ts +33 -0
- package/src/components/dpqlEditor/useDpqlSession.ts +20 -4
- package/src/components/form/engine/CompactRow.tsx +487 -160
- package/src/components/form/engine/CompactToolbar.tsx +10 -3
- package/src/components/form/engine/FormEngine.stories.tsx +1269 -201
- package/src/components/form/engine/FormEngine.tsx +922 -270
- package/src/components/form/engine/FormEngineStickyHeaders.stories.tsx +331 -0
- package/src/components/form/engine/FormFieldsSkeleton.tsx +77 -0
- package/src/components/form/engine/OptionFieldMessages.tsx +300 -14
- package/src/components/form/engine/_structuredData/SchemaDataView.tsx +94 -3
- package/src/components/form/engine/compactRowContext.ts +15 -6
- package/src/components/form/engine/compactRowStyles.ts +56 -2
- package/src/components/form/engine/compactToolbarContext.ts +1 -1
- package/src/components/form/engine/optionActions.ts +89 -1
- package/src/components/form/engine/optionsContext.ts +24 -0
- package/src/components/form/engine/readFirst.ts +88 -8
- package/src/components/form/engine/rendererTypes.ts +48 -4
- package/src/components/form/engine/rowFocus.ts +101 -0
- package/src/components/form/engine/rowMenuContext.ts +159 -0
- package/src/components/form/engine/rowOpenPicker.ts +27 -0
- package/src/components/form/engine/typeChoices.ts +63 -0
- package/src/components/form/expressions/DpqlRendering.tsx +85 -0
- package/src/components/form/expressions/ExpressionField.stories.tsx +826 -48
- package/src/components/form/expressions/ExpressionField.tsx +269 -55
- package/src/components/form/expressions/argumentPresence.ts +213 -0
- package/src/components/form/expressions/builder/ExpressionBuilder.stories.tsx +38 -21
- package/src/components/form/expressions/builder/argumentLabel.tsx +10 -4
- package/src/components/form/expressions/builder/index.tsx +39 -81
- package/src/components/form/expressions/builder/renderTemplate.tsx +23 -56
- package/src/components/form/expressions/dpqlMockLanguage.ts +565 -0
- package/src/components/form/expressions/dpqlMockLsp.ts +109 -83
- package/src/components/form/expressions/mockExpressions.ts +8 -4
- package/src/components/form/expressions/renderExpressionToText.ts +112 -22
- package/src/components/form/expressions/types.ts +17 -2
- package/src/components/form/expressions/useExpressions.ts +5 -1
- package/src/components/form/expressions/useRenderExpression.ts +43 -127
- package/src/components/form/fields/Field.tsx +102 -20
- package/src/components/form/fields/allowed-values/AllowedValues.tsx +106 -44
- package/src/components/form/fields/auto/AutoFormField.stories.tsx +85 -18
- package/src/components/form/fields/auto/AutoFormField.tsx +97 -21
- package/src/components/form/fields/date/Date.tsx +17 -1
- package/src/components/form/fields/long-string/LongString.tsx +15 -3
- package/src/components/form/fields/multi-select/MultiSelectFormField.tsx +65 -6
- package/src/components/form/fields/number/Number.tsx +25 -0
- package/src/components/form/fields/rich-text/RichText.tsx +248 -30
- package/src/components/form/fields/select/Select.stories.tsx +392 -0
- package/src/components/form/fields/select/Select.tsx +164 -27
- package/src/components/form/fields/select/SelectCollection.tsx +350 -6
- package/src/components/form/fields/template/ReadOnlyTemplateTag.tsx +4 -2
- package/src/components/form/fields/template/TemplateField.stories.tsx +93 -14
- package/src/components/form/fields/template/TemplateField.tsx +825 -131
- package/src/components/form/fields/template/TemplateText.tsx +115 -0
- package/src/components/form/index.tsx +4 -0
- package/src/components/log/Log.stories.tsx +2 -1
- package/src/components/searchFilterBar/SearchFilterBar.stories.tsx +3 -3
- package/src/components/smartEditor/SmartEditor.tsx +41 -9
- package/src/components/smartEditor/__fixtures__/mockLspServer.ts +52 -3
- package/src/components/smartEditor/useLspSession.ts +21 -3
- package/src/components/supportTicket/TicketReplyBox.tsx +8 -4
- package/src/components/ticketThread/TicketThread.stories.tsx +1 -0
- package/src/helpers/common.ts +7 -3
- package/src/helpers/dpqlDetection.ts +209 -0
- package/src/helpers/optionUiTypes.ts +38 -0
- package/src/helpers/options.ts +96 -0
- package/src/helpers/templateItems.ts +81 -0
- package/src/helpers/templateText.ts +350 -0
- package/src/helpers/templates.ts +94 -41
- package/src/helpers/validations.ts +203 -51
- package/src/hooks/useFetch/useFetch.stories.tsx +6 -5
- package/src/hooks/useFetch/useFetch.tsx +53 -7
- package/src/hooks/useStorage/useStorage.stories.tsx +2 -1
- package/src/hooks/useTemplates.ts +41 -0
- package/src/hooks/useWebSocket/useWebsocket.stories.tsx +2 -1
- package/src/index.tsx +14 -1
- package/src/stores/currentUser/currentUser.stories.tsx +2 -1
- package/src/stories/storyNetwork.ts +92 -0
- package/src/utils/fetch.ts +311 -21
- package/src/utils/lspClient.ts +68 -11
- package/src/utils/websocket.ts +20 -9
- package/dist/components/form/engine/__fixtures__/basicFormOptions.d.ts +0 -73
- package/dist/components/form/engine/__fixtures__/basicFormOptions.d.ts.map +0 -1
- package/dist/components/form/engine/__fixtures__/basicFormOptions.js +0 -317
- package/dist/components/form/engine/__fixtures__/basicFormOptions.js.map +0 -1
- package/dist/components/form/engine/__fixtures__/fieldChromeOptions.d.ts +0 -41
- package/dist/components/form/engine/__fixtures__/fieldChromeOptions.d.ts.map +0 -1
- package/dist/components/form/engine/__fixtures__/fieldChromeOptions.js +0 -45
- package/dist/components/form/engine/__fixtures__/fieldChromeOptions.js.map +0 -1
- package/dist/components/form/expressions/dpqlMockLsp.d.ts +0 -3
- package/dist/components/form/expressions/dpqlMockLsp.d.ts.map +0 -1
- package/dist/components/form/expressions/dpqlMockLsp.js +0 -91
- package/dist/components/form/expressions/dpqlMockLsp.js.map +0 -1
- package/dist/components/form/fields/template/__fixtures__/longExampleValue.d.ts +0 -2
- package/dist/components/form/fields/template/__fixtures__/longExampleValue.d.ts.map +0 -1
- package/dist/components/form/fields/template/__fixtures__/longExampleValue.js +0 -9
- package/dist/components/form/fields/template/__fixtures__/longExampleValue.js.map +0 -1
- package/dist/components/smartEditor/__fixtures__/mockLspServer.d.ts +0 -55
- package/dist/components/smartEditor/__fixtures__/mockLspServer.d.ts.map +0 -1
- package/dist/components/smartEditor/__fixtures__/mockLspServer.js +0 -126
- package/dist/components/smartEditor/__fixtures__/mockLspServer.js.map +0 -1
- package/dist/stories/Data/fileFieldArgSchema.json +0 -86
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReqoreP, ReqorePanel } from '@qoretechnologies/reqore';
|
|
2
2
|
import { GAP_FROM_SIZE, TSizes } from '@qoretechnologies/reqore/dist/constants/sizes';
|
|
3
|
-
import styled from 'styled-components';
|
|
3
|
+
import styled, { css } from 'styled-components';
|
|
4
4
|
|
|
5
5
|
// Styled primitives for the compact (read-first) rows and their editor cards.
|
|
6
6
|
// Shared between FormEngine and the extracted CompactRow component.
|
|
@@ -64,7 +64,31 @@ export const StyledCompactPanel = styled(ReqorePanel)<{
|
|
|
64
64
|
/** True when the toolbar renders no search row (hidden via `compactToolbar`,
|
|
65
65
|
* self-hidden on a single-option form, or no toolbar at all). */
|
|
66
66
|
$tightHeader?: boolean;
|
|
67
|
+
/** True when the status boxes inside pin their headers. */
|
|
68
|
+
$stickyBoxes?: boolean;
|
|
67
69
|
}>`
|
|
70
|
+
/* The wrapper must not clip, or nothing INSIDE it can pin.
|
|
71
|
+
|
|
72
|
+
ReqorePanel sets its wrapper to \`overflow: hidden\` unless its own header
|
|
73
|
+
is sticky — and a clipping box is a scrollport, so a status box header
|
|
74
|
+
inside it resolves against the wrapper instead of the page and stops
|
|
75
|
+
pinning. That coupling is right for the panel's own header and wrong for
|
|
76
|
+
its descendants': a host that turns this form's toolbar off (a two-field
|
|
77
|
+
form inside a longer page, where a pinned search bar is the biggest thing
|
|
78
|
+
on screen and the least useful) was silently turning the box headers off
|
|
79
|
+
with it.
|
|
80
|
+
|
|
81
|
+
The clip is the panel's rounded corners, and this panel is transparent and
|
|
82
|
+
border-less — \`flat raised minimal\`, no background of its own — so there
|
|
83
|
+
is nothing for it to clip. */
|
|
84
|
+
${({ $stickyBoxes }) =>
|
|
85
|
+
$stickyBoxes ?
|
|
86
|
+
css`
|
|
87
|
+
&&& {
|
|
88
|
+
overflow: visible;
|
|
89
|
+
}
|
|
90
|
+
`
|
|
91
|
+
: ''}
|
|
68
92
|
> .reqore-panel-title {
|
|
69
93
|
/* The blur + translateZ exist only to make the STICKY top-level toolbar ghost
|
|
70
94
|
content beneath it; a nested sub-form's header isn't sticky, so skip them
|
|
@@ -154,7 +178,12 @@ export const StyledGroupHeaderLine = styled.span<{ $color: string }>`
|
|
|
154
178
|
// a barely-there accent border + a ~5%-opacity tint, NOT the loud intent border a
|
|
155
179
|
// stock ReqorePanel draws. `$accent` is the box's theme colour (warning/success/
|
|
156
180
|
// muted).
|
|
157
|
-
export const StyledStatusBox = styled(ReqorePanel)<{
|
|
181
|
+
export const StyledStatusBox = styled(ReqorePanel)<{
|
|
182
|
+
$accent: string;
|
|
183
|
+
$bg?: string;
|
|
184
|
+
/** The page's own background, for the PINNED header — see below. */
|
|
185
|
+
$surface?: string;
|
|
186
|
+
}>`
|
|
158
187
|
&&& {
|
|
159
188
|
border: 1px solid ${({ $accent }) => `${$accent}33`};
|
|
160
189
|
/* $bg lets the muted "Optional" box opt into a darker, recessed surface
|
|
@@ -162,6 +191,31 @@ export const StyledStatusBox = styled(ReqorePanel)<{ $accent: string; $bg?: stri
|
|
|
162
191
|
background: ${({ $accent, $bg }) => $bg || `${$accent}1f`};
|
|
163
192
|
border-radius: 10px;
|
|
164
193
|
}
|
|
194
|
+
|
|
195
|
+
/* A PINNED header needs a surface of its own.
|
|
196
|
+
|
|
197
|
+
The box's tint lives on the wrapper, behind the header, and a \`minimal\`
|
|
198
|
+
panel header is transparent — which is right while the header sits in the
|
|
199
|
+
flow over its own box, and wrong the moment it pins, because the rows then
|
|
200
|
+
scroll THROUGH it. Reqore's backdrop blur softens them but a 12% tint over
|
|
201
|
+
moving text still reads as two overlaid labels.
|
|
202
|
+
|
|
203
|
+
So repaint the pinned header as the box looks at rest: an opaque layer of
|
|
204
|
+
the page background with the box's own translucent tint composited on top,
|
|
205
|
+
which is exactly what the eye sees where the box meets the page. The
|
|
206
|
+
Optional box already carries an opaque \`$bg\`, so that is used as-is.
|
|
207
|
+
|
|
208
|
+
Only when \`$surface\` is supplied — i.e. only on a form that pins at all —
|
|
209
|
+
so an unpinned box is pixel-identical to before. */
|
|
210
|
+
${({ $surface, $accent, $bg }) =>
|
|
211
|
+
$surface ?
|
|
212
|
+
css`
|
|
213
|
+
&&& > .reqore-panel-title {
|
|
214
|
+
background-color: ${$bg || $surface};
|
|
215
|
+
${$bg ? '' : `background-image: linear-gradient(${$accent}1f, ${$accent}1f);`}
|
|
216
|
+
}
|
|
217
|
+
`
|
|
218
|
+
: ''}
|
|
165
219
|
`;
|
|
166
220
|
|
|
167
221
|
// "One of the below is required" cluster box — wraps the members of an unmet
|
|
@@ -35,7 +35,7 @@ export interface ICompactToolbarContext {
|
|
|
35
35
|
// Completion meter
|
|
36
36
|
invalidCount: number;
|
|
37
37
|
attentionCount: number;
|
|
38
|
-
completion: { set: number; total: number; pct: number };
|
|
38
|
+
completion: { set: number; done: number; total: number; pct: number };
|
|
39
39
|
// Invalid-fields banner (pinned in the sticky header)
|
|
40
40
|
showInvalidOnly: boolean;
|
|
41
41
|
onToggleInvalidOnly: () => void;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IReqoreDropdownItem } from '@qoretechnologies/reqore/dist/components/Dropdown/list';
|
|
2
|
+
import {
|
|
3
|
+
IReqorePanelAction,
|
|
4
|
+
IReqorePanelSubAction,
|
|
5
|
+
} from '@qoretechnologies/reqore/dist/components/Panel';
|
|
2
6
|
import { IQorusFormField, IQorusFormSchema } from '@qoretechnologies/ts-toolkit';
|
|
3
7
|
|
|
4
8
|
/**
|
|
@@ -38,3 +42,87 @@ export const resolveOptionActions = (
|
|
|
38
42
|
|
|
39
43
|
return (actions ?? []).filter((action): action is IReqorePanelAction => !!action);
|
|
40
44
|
};
|
|
45
|
+
|
|
46
|
+
/** How many injected actions a row shows as buttons before the rest go into its menu. */
|
|
47
|
+
export const MAX_INLINE_OPTION_ACTIONS = 2;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Which injected actions stay as buttons, and which move into the row's menu.
|
|
51
|
+
*
|
|
52
|
+
* Everything moves on touch and on narrow viewports (`collapse`) — a button
|
|
53
|
+
* that waits for a hover is unreachable without one — and anything past the
|
|
54
|
+
* inline cap moves regardless, so a consumer injecting ten actions can never
|
|
55
|
+
* push the row's value out of view. Both render paths decide it here.
|
|
56
|
+
*/
|
|
57
|
+
export const splitOptionActions = (
|
|
58
|
+
actions: IReqorePanelAction[],
|
|
59
|
+
collapse: boolean
|
|
60
|
+
): [IReqorePanelAction[], IReqorePanelAction[]] =>
|
|
61
|
+
collapse ?
|
|
62
|
+
[[], actions]
|
|
63
|
+
: [actions.slice(0, MAX_INLINE_OPTION_ACTIONS), actions.slice(MAX_INLINE_OPTION_ACTIONS)];
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* An injected action as a row in a menu.
|
|
67
|
+
*
|
|
68
|
+
* A panel action labels itself with `label`, but an icon-only one (the IDE's
|
|
69
|
+
* AI-assist button) carries its name in the tooltip — and a menu row has no
|
|
70
|
+
* hover to fall back on.
|
|
71
|
+
*/
|
|
72
|
+
export const optionActionAsMenuItem = (
|
|
73
|
+
action: IReqorePanelAction,
|
|
74
|
+
index: number
|
|
75
|
+
): IReqoreDropdownItem => ({
|
|
76
|
+
/* A menu row's label has to be text. `tooltip` may be a tooltip OBJECT
|
|
77
|
+
(`IReqoreTooltip`), which is why this was cast before — an action with a
|
|
78
|
+
configured tooltip and no label put that object where a string belongs. */
|
|
79
|
+
label:
|
|
80
|
+
action.label ??
|
|
81
|
+
(typeof action.tooltip === 'string' ? action.tooltip : undefined) ??
|
|
82
|
+
`Action ${index + 1}`,
|
|
83
|
+
icon: action.icon,
|
|
84
|
+
intent: action.intent,
|
|
85
|
+
disabled: action.disabled,
|
|
86
|
+
className: action.className,
|
|
87
|
+
onClick: () => action.onClick?.(),
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
export interface IOptionRowActionsInput {
|
|
91
|
+
/** The consumer's actions for this option, already resolved. */
|
|
92
|
+
injected: IReqorePanelAction[];
|
|
93
|
+
/** Move every injected action into the menu (touch, narrow viewport). */
|
|
94
|
+
collapse: boolean;
|
|
95
|
+
/** The row's own secondary actions; a falsy entry is one that does not apply. */
|
|
96
|
+
menu: (IReqorePanelSubAction | false | null | undefined | 0 | '')[];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* A classic form row's header actions.
|
|
101
|
+
*
|
|
102
|
+
* Injected actions stay as buttons up to the inline cap; the rest, and the
|
|
103
|
+
* row's own secondary actions, go into ONE ⋯ menu that is always drawn, so
|
|
104
|
+
* nothing the row offers is reachable only by hovering it.
|
|
105
|
+
*/
|
|
106
|
+
export const optionRowActions = ({
|
|
107
|
+
injected,
|
|
108
|
+
collapse,
|
|
109
|
+
menu,
|
|
110
|
+
}: IOptionRowActionsInput): IReqorePanelAction[] => {
|
|
111
|
+
const [inline, overflow] = splitOptionActions(injected, collapse);
|
|
112
|
+
const items: IReqorePanelSubAction[] = [
|
|
113
|
+
...overflow.map(optionActionAsMenuItem),
|
|
114
|
+
...menu.filter((item): item is IReqorePanelSubAction => !!item),
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
const more: IReqorePanelAction = {
|
|
118
|
+
icon: 'More2Fill',
|
|
119
|
+
size: 'tiny',
|
|
120
|
+
minimal: true,
|
|
121
|
+
flat: true,
|
|
122
|
+
className: 'options-item-more',
|
|
123
|
+
tooltip: 'More actions',
|
|
124
|
+
actions: items,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
return [...inline, ...(items.length ? [more] : [])];
|
|
128
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { IQorusFormSchema, TQorusForm } from '@qoretechnologies/ts-toolkit';
|
|
2
|
+
import { createContext } from 'use-context-selector';
|
|
3
|
+
|
|
4
|
+
/** The form a field is standing in: what it declares, and what it currently holds. */
|
|
5
|
+
export interface IOptionsContext {
|
|
6
|
+
schema?: IQorusFormSchema;
|
|
7
|
+
value?: TQorusForm;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The surrounding form, for a renderer that has to judge one field against its
|
|
12
|
+
* SIBLINGS — an allowed value gated on another field's answer, for instance.
|
|
13
|
+
*
|
|
14
|
+
* It lives in a module of its own rather than in `FormEngine`, which imports
|
|
15
|
+
* the field renderers that read it: a renderer importing the engine back would
|
|
16
|
+
* close a cycle around a value created at module scope, and the context would
|
|
17
|
+
* be `undefined` for whichever module happened to be evaluated first.
|
|
18
|
+
*
|
|
19
|
+
* An empty default is load-bearing. `value` is `undefined` only when there is
|
|
20
|
+
* no form around the renderer at all — a picker mounted on its own, a story, a
|
|
21
|
+
* test — and a predicate about siblings has nothing to say there. Inside a form
|
|
22
|
+
* it is always an object, empty or not.
|
|
23
|
+
*/
|
|
24
|
+
export const OptionsContext = createContext<IOptionsContext>({});
|
|
@@ -10,6 +10,7 @@ import { renderExpressionToText } from '../expressions/renderExpressionToText';
|
|
|
10
10
|
import { IExpressionValue } from '../expressions/types';
|
|
11
11
|
import yaml from 'js-yaml';
|
|
12
12
|
import { formatTimeoutValue, richtextToString } from '../../../helpers/common';
|
|
13
|
+
import { firstDeclaredType } from '../../../helpers/optionUiTypes';
|
|
13
14
|
|
|
14
15
|
/** "N noun" with naive pluralisation ("1 item", "2 items"). */
|
|
15
16
|
const pluralize = (count: number, noun: string): string =>
|
|
@@ -224,7 +225,7 @@ export const shouldAutoCollapseCompactAllowedValueOption = (
|
|
|
224
225
|
* user chooses either boolean value in compact mode, the choice is complete
|
|
225
226
|
* and the inline editor can close without a separate confirmation. */
|
|
226
227
|
export const isCompactBooleanOption = (schema: TQorusFormFieldSchema | undefined): boolean => {
|
|
227
|
-
const type = (schema?.ui_type || schema?.type)?.toLowerCase();
|
|
228
|
+
const type = firstDeclaredType(schema?.ui_type || schema?.type)?.toLowerCase();
|
|
228
229
|
return type === 'bool' || type === 'boolean';
|
|
229
230
|
};
|
|
230
231
|
|
|
@@ -316,6 +317,31 @@ export const getAllowedValueImage = (
|
|
|
316
317
|
return (match?.image as string) || undefined;
|
|
317
318
|
};
|
|
318
319
|
|
|
320
|
+
/**
|
|
321
|
+
* The selected option's ICON, when it carries one and no logo — for the value
|
|
322
|
+
* cell.
|
|
323
|
+
*
|
|
324
|
+
* The same idea as {@link getAllowedValueImage} and read for the same reason:
|
|
325
|
+
* an option's mark belongs beside the value it names. Only images were rendered,
|
|
326
|
+
* so a picker whose entries are distinguished by ICON — an interface-kind list
|
|
327
|
+
* where every entry is a bare word, `Service`, `Job`, `Qog` — showed each mark
|
|
328
|
+
* while choosing and then dropped it the moment the row went read-only, which is
|
|
329
|
+
* the surface a reader spends the most time on.
|
|
330
|
+
*
|
|
331
|
+
* The image wins where an option has both: a logo is the more specific mark, and
|
|
332
|
+
* an icon standing behind it is a fallback rather than a second thing to draw.
|
|
333
|
+
*/
|
|
334
|
+
export const getAllowedValueIcon = (
|
|
335
|
+
value: unknown,
|
|
336
|
+
schema?: TQorusFormFieldSchema
|
|
337
|
+
): string | undefined => {
|
|
338
|
+
const match = findAllowedOption(value, schema);
|
|
339
|
+
if (!match || match.image) {
|
|
340
|
+
return undefined;
|
|
341
|
+
}
|
|
342
|
+
return (match.icon as string) || undefined;
|
|
343
|
+
};
|
|
344
|
+
|
|
319
345
|
/** Clamp an RGB channel to a 0–255 integer. */
|
|
320
346
|
const clampChannel = (n: number): number => Math.max(0, Math.min(255, Math.round(n)));
|
|
321
347
|
const toHexPart = (n: number): string => clampChannel(n).toString(16).padStart(2, '0');
|
|
@@ -556,6 +582,36 @@ export const summariseMarkdown = (value: unknown): string => {
|
|
|
556
582
|
return capSummary(prose);
|
|
557
583
|
};
|
|
558
584
|
|
|
585
|
+
/**
|
|
586
|
+
* The expression AST a field holds, whichever shape it arrived in.
|
|
587
|
+
*
|
|
588
|
+
* An expression arrives in TWO shapes, and only the flat one used to be
|
|
589
|
+
* checked. At runtime the editor writes the flag onto the option
|
|
590
|
+
* (`{ is_expression: true, value: ast }`); a value read back from a saved draft
|
|
591
|
+
* carries the envelope NESTED (`{ value: { is_expression: true, value: ast } }`)
|
|
592
|
+
* with no flag on the option at all. Missing the nested shape sent a reloaded
|
|
593
|
+
* expression to the generic formatter, which printed the AST — the row showed
|
|
594
|
+
* `is_expression true / value / exp + / args 1 2` where the expression should
|
|
595
|
+
* be.
|
|
596
|
+
*
|
|
597
|
+
* Exported because the SUMMARY is not the only place that has to know. The AST
|
|
598
|
+
* is how an expression is stored, not what it is, so nothing may draw it as
|
|
599
|
+
* data: `CompactRow` asks this before deciding a hash-shaped value has earned a
|
|
600
|
+
* structured inset. Answering it in one place is what keeps the row's two
|
|
601
|
+
* halves — the line and the inset under it — talking about the same value.
|
|
602
|
+
*/
|
|
603
|
+
export const getExpressionAst = (option?: {
|
|
604
|
+
is_expression?: boolean;
|
|
605
|
+
value?: unknown;
|
|
606
|
+
}): IExpressionValue | undefined =>
|
|
607
|
+
option?.is_expression ? (option?.value as IExpressionValue | undefined)
|
|
608
|
+
: (
|
|
609
|
+
(option?.value as { is_expression?: boolean; value?: IExpressionValue } | undefined)
|
|
610
|
+
?.is_expression
|
|
611
|
+
) ?
|
|
612
|
+
(option?.value as { value?: IExpressionValue }).value
|
|
613
|
+
: undefined;
|
|
614
|
+
|
|
559
615
|
export const formatOptionValue = (
|
|
560
616
|
option?: IQorusFormField,
|
|
561
617
|
schema?: TQorusFormFieldSchema
|
|
@@ -572,11 +628,13 @@ export const formatOptionValue = (
|
|
|
572
628
|
return '••••••';
|
|
573
629
|
}
|
|
574
630
|
|
|
575
|
-
|
|
631
|
+
const expressionAst = getExpressionAst(option);
|
|
632
|
+
|
|
633
|
+
if (expressionAst !== undefined) {
|
|
576
634
|
// Offline summary of the {exp,args} AST already in the form value — the
|
|
577
635
|
// same client-side renderer the editor's "Explain" seam falls back to when
|
|
578
636
|
// the LSP is unreachable. The drill-in editor shows the canonical DPQL.
|
|
579
|
-
return renderExpressionToText(
|
|
637
|
+
return renderExpressionToText(expressionAst) || 'Expression';
|
|
580
638
|
}
|
|
581
639
|
|
|
582
640
|
// schema-definition is stored as a hash envelope; summarise it as the schema
|
|
@@ -792,7 +850,10 @@ export const getOptionGroupLabel = (
|
|
|
792
850
|
/** Completion summary for the read-first progress meter. */
|
|
793
851
|
export interface IReadFirstCompletion {
|
|
794
852
|
total: number;
|
|
853
|
+
/** Fields holding a value, whether or not anything is wrong with it. */
|
|
795
854
|
set: number;
|
|
855
|
+
/** Fields holding a value that nothing is flagging — what the meter fills. */
|
|
856
|
+
done: number;
|
|
796
857
|
pct: number;
|
|
797
858
|
}
|
|
798
859
|
|
|
@@ -831,14 +892,33 @@ export const getReadFirstBucket = (status: TReadFirstStatus): 'attention' | 'set
|
|
|
831
892
|
|
|
832
893
|
/** Count how many of the shown options have a value set, for the progress meter. */
|
|
833
894
|
export const getReadFirstCompletion = (
|
|
834
|
-
shownOptions: Record<string, IQorusFormField | undefined> = {}
|
|
895
|
+
shownOptions: Record<string, IQorusFormField | undefined> = {},
|
|
896
|
+
/**
|
|
897
|
+
* Whether the form flags this field as needing attention. Optional: without
|
|
898
|
+
* it the meter falls back to counting values alone, which is what a caller
|
|
899
|
+
* with no bucketing of its own can honestly say.
|
|
900
|
+
*/
|
|
901
|
+
needsAttention?: (name: string) => boolean
|
|
835
902
|
): IReadFirstCompletion => {
|
|
836
903
|
const names = Object.keys(shownOptions);
|
|
837
904
|
const total = names.length;
|
|
838
|
-
const
|
|
839
|
-
const
|
|
840
|
-
|
|
841
|
-
|
|
905
|
+
const hasValue = (name: string) => !isOptionValueEmpty(shownOptions[name]?.value);
|
|
906
|
+
const set = names.filter(hasValue).length;
|
|
907
|
+
/* "Set" and "needs attention" are not opposites. A field can hold a value and
|
|
908
|
+
still be wrong — one that fails validation, or one the host has flagged
|
|
909
|
+
because something INSIDE it is unfinished — and counting those as progress
|
|
910
|
+
is how a form comes to report 100% while the box beneath it says a field
|
|
911
|
+
needs attention.
|
|
912
|
+
|
|
913
|
+
It also cost the meter its amber run: the bar draws attention from `set%`
|
|
914
|
+
onward, so a field counted in both pushed that run past the right edge,
|
|
915
|
+
where `overflow: hidden` swallowed it. The one visual signal that something
|
|
916
|
+
was outstanding was the one thing the double-count hid. */
|
|
917
|
+
const done =
|
|
918
|
+
needsAttention ? names.filter((name) => hasValue(name) && !needsAttention(name)).length : set;
|
|
919
|
+
const pct = total ? Math.round((done / total) * 100) : 0;
|
|
920
|
+
|
|
921
|
+
return { total, set, done, pct };
|
|
842
922
|
};
|
|
843
923
|
|
|
844
924
|
/** What the "first field to fix" selector needs to know about one field.
|
|
@@ -1,4 +1,37 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IReqoreFormTemplates } from '@qoretechnologies/reqore/dist/components/Textarea';
|
|
2
|
+
import { firstDeclaredType } from '../../../helpers/optionUiTypes';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A field schema that carries a template list of its own.
|
|
6
|
+
*
|
|
7
|
+
* `templates` is deliberately NOT added to `TQorusFormFieldSchema`: that type is
|
|
8
|
+
* owned by ts-toolkit and shared with consumers that have no notion of a form
|
|
9
|
+
* engine, so the capability is read through this narrow view instead of widening
|
|
10
|
+
* the shared type from here. A schema that sets it is offering a list scoped to
|
|
11
|
+
* one field rather than to the whole form.
|
|
12
|
+
*/
|
|
13
|
+
export type TFieldWithOwnTemplates = {
|
|
14
|
+
templates?: IReqoreFormTemplates;
|
|
15
|
+
/**
|
|
16
|
+
* The token grammar this field's value is WRITTEN in.
|
|
17
|
+
*
|
|
18
|
+
* A host may spell a reference in a grammar that is not reqraft's — a Qorus
|
|
19
|
+
* test writes `$._case.mode`, which has no `$key:` in it at all — and a field
|
|
20
|
+
* that speaks one says so here, exactly as it hands down its own `templates`.
|
|
21
|
+
* Declaring it on the schema is what lets every surface that draws the value
|
|
22
|
+
* agree about it, instead of printing the raw token the author never typed.
|
|
23
|
+
*
|
|
24
|
+
* Both directions read it: the read-only renderings
|
|
25
|
+
* (`templateTextSegments`) and the rich-text editor a row opens
|
|
26
|
+
* (`templateTextToNodes`, through `RichTextFormField`'s `templateToken`
|
|
27
|
+
* prop). They resolve references with the same code, so a row and the editor
|
|
28
|
+
* it opens cannot disagree about what one is.
|
|
29
|
+
*
|
|
30
|
+
* A `RegExp` or its source: a schema that crossed a serialization boundary
|
|
31
|
+
* carries the string.
|
|
32
|
+
*/
|
|
33
|
+
templateToken?: RegExp | string;
|
|
34
|
+
};
|
|
2
35
|
|
|
3
36
|
/**
|
|
4
37
|
* A schema entry carries two type-ish keys with different jobs:
|
|
@@ -41,6 +74,15 @@ export const BUILT_IN_RENDERER_ONLY_UI_TYPES: readonly string[] = [
|
|
|
41
74
|
'tool-catalog',
|
|
42
75
|
];
|
|
43
76
|
|
|
77
|
+
/**
|
|
78
|
+
* A `ui_type` as the predicate takes it: any name, not only a `TQorusType`.
|
|
79
|
+
* The names it exists to recognise are open-ended — `cron` is not a
|
|
80
|
+
* `TQorusType`, and neither is an editor a consumer declares — so typing the
|
|
81
|
+
* argument as the shared union made the predicate uncallable for exactly the
|
|
82
|
+
* values it is for.
|
|
83
|
+
*/
|
|
84
|
+
export type TRendererTypeName = string | readonly string[];
|
|
85
|
+
|
|
44
86
|
/**
|
|
45
87
|
* Build the renderer-only predicate for one FormEngine instance.
|
|
46
88
|
*
|
|
@@ -52,11 +94,13 @@ export const BUILT_IN_RENDERER_ONLY_UI_TYPES: readonly string[] = [
|
|
|
52
94
|
*/
|
|
53
95
|
export const createRendererOnlyUiTypeCheck = (
|
|
54
96
|
extraTypes?: readonly string[]
|
|
55
|
-
): ((type?:
|
|
97
|
+
): ((type?: TRendererTypeName) => boolean) => {
|
|
56
98
|
const known = new Set<string>([...BUILT_IN_RENDERER_ONLY_UI_TYPES, ...(extraTypes ?? [])]);
|
|
57
99
|
|
|
58
|
-
return (type?:
|
|
59
|
-
|
|
100
|
+
return (type?: TRendererTypeName): boolean => {
|
|
101
|
+
const declared = firstDeclaredType(type);
|
|
102
|
+
return declared !== undefined && known.has(declared);
|
|
103
|
+
};
|
|
60
104
|
};
|
|
61
105
|
|
|
62
106
|
/** The default predicate — built-ins only, for module-scope callers with no props. */
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which control an open compact row hands the caret to.
|
|
3
|
+
*
|
|
4
|
+
* A row's editor is whatever the field's type asks for, and only some of those
|
|
5
|
+
* take typed text. A pick-one renders `ReqoreCheckbox`es (a `[tabindex]`
|
|
6
|
+
* element), a selector renders a `<button>`, a code field a `[contenteditable]`
|
|
7
|
+
* — so a scan that looked for `input`, `textarea` and `[contenteditable]` alone
|
|
8
|
+
* found nothing on most of the first questions a form asks ("which kind?",
|
|
9
|
+
* "which connection?", "which interface?"). The row opened and the caret stayed
|
|
10
|
+
* on whatever made it open.
|
|
11
|
+
*
|
|
12
|
+
* Text entry wins when the row offers it. Every editor that takes typing also
|
|
13
|
+
* draws affordances around it — a template picker, a type menu, a clear button
|
|
14
|
+
* — and those come first in document order often enough that "the first
|
|
15
|
+
* focusable element" would answer a text field with a button beside it.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** Controls the reader types into. */
|
|
19
|
+
const TEXT_ENTRY_SELECTOR =
|
|
20
|
+
'input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), [contenteditable="true"]';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Everything else a row can offer. `[tabindex]` is what carries reqore's own
|
|
24
|
+
* controls: a checkbox is an icon element made focusable, not an `<input>`.
|
|
25
|
+
*/
|
|
26
|
+
const OTHER_CONTROL_SELECTOR =
|
|
27
|
+
'button:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Subtrees inside the row's value cell that are NOT this field's editor: a
|
|
31
|
+
* sibling field absorbed into this row (a different field, which the engine did
|
|
32
|
+
* not open) and the schema-message strip above the editor (guidance about the
|
|
33
|
+
* value, never a place to put one).
|
|
34
|
+
*/
|
|
35
|
+
const NOT_THE_FIELDS_OWN_EDITOR = '.options-readfirst-absorbed, .options-readfirst-info-panel';
|
|
36
|
+
|
|
37
|
+
const belongsToTheFieldsOwnEditor = (container: HTMLElement, element: Element): boolean => {
|
|
38
|
+
const foreign = element.closest(NOT_THE_FIELDS_OWN_EDITOR);
|
|
39
|
+
// `closest` walks past the container too, so a match only disqualifies the
|
|
40
|
+
// element when it is inside THIS container.
|
|
41
|
+
return !foreign || !container.contains(foreign);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const firstMatch = (container: HTMLElement, selector: string): HTMLElement | undefined => {
|
|
45
|
+
const matches = Array.from(container.querySelectorAll<HTMLElement>(selector));
|
|
46
|
+
return matches.find(
|
|
47
|
+
(element) =>
|
|
48
|
+
belongsToTheFieldsOwnEditor(container, element) &&
|
|
49
|
+
// An element hidden from assistive technology is not a destination for a
|
|
50
|
+
// caret either — reqore draws decorative, focusable-looking chrome that
|
|
51
|
+
// way.
|
|
52
|
+
!element.closest('[aria-hidden="true"]')
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The control an open row should focus, or `undefined` when it offers none —
|
|
58
|
+
* a read-only preview, or an editor that has not mounted yet (see the caller,
|
|
59
|
+
* which watches for it to arrive).
|
|
60
|
+
*
|
|
61
|
+
* @param container the row's value cell
|
|
62
|
+
*/
|
|
63
|
+
export const findRowFocusTarget = (
|
|
64
|
+
container: HTMLElement | null | undefined
|
|
65
|
+
): HTMLElement | undefined => {
|
|
66
|
+
if (!container) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
return (
|
|
70
|
+
firstMatch(container, TEXT_ENTRY_SELECTOR) ?? firstMatch(container, OTHER_CONTROL_SELECTOR)
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Controls whose ONLY behaviour is to reveal the choices.
|
|
76
|
+
*
|
|
77
|
+
* A row that opens hands the caret to the control it offers, and for most
|
|
78
|
+
* editors that is the end of it: a text box takes typing, a pick-one's
|
|
79
|
+
* checkboxes take a click. A PICKER is different — its closed state prints the
|
|
80
|
+
* value it already holds, which is the very thing the read row printed, so
|
|
81
|
+
* opening the row changed nothing on screen and the author had to click a
|
|
82
|
+
* second time to see the list. Read-first belongs to the collapsed row; it must
|
|
83
|
+
* not be the answer twice.
|
|
84
|
+
*
|
|
85
|
+
* Declared with `aria-haspopup`, which is what the attribute means and is
|
|
86
|
+
* already the contract with assistive technology — so a host's own editor opts
|
|
87
|
+
* in by being accessible rather than by knowing about this file. `aria-expanded`
|
|
88
|
+
* is respected: a picker that is already showing its list is not re-activated.
|
|
89
|
+
*/
|
|
90
|
+
const PICKER_TRIGGER_SELECTOR =
|
|
91
|
+
'[aria-haspopup="listbox"], [aria-haspopup="dialog"], [aria-haspopup="menu"], [aria-haspopup="tree"], [aria-haspopup="grid"]';
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Whether this control is a picker that is still closed — i.e. whether
|
|
95
|
+
* activating it is what "open the editor" means for this row.
|
|
96
|
+
*/
|
|
97
|
+
export const isClosedPickerTrigger = (element: HTMLElement | null | undefined): boolean =>
|
|
98
|
+
!!element &&
|
|
99
|
+
typeof element.matches === 'function' &&
|
|
100
|
+
element.matches(PICKER_TRIGGER_SELECTOR) &&
|
|
101
|
+
element.getAttribute('aria-expanded') !== 'true';
|