@qoretechnologies/reqraft 0.10.25 → 0.10.26
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 +52 -23
- package/design/COMPACT_ENGINE_REDESIGN.md +156 -0
- package/design/FORM_ENGINE_COMPACT_UX_PLAN.md +353 -0
- package/dist/components/FocusedEditing/index.d.ts +9 -1
- package/dist/components/FocusedEditing/index.d.ts.map +1 -1
- package/dist/components/FocusedEditing/index.js +2 -2
- package/dist/components/FocusedEditing/index.js.map +1 -1
- package/dist/components/composer/Composer.d.ts +108 -0
- package/dist/components/composer/Composer.d.ts.map +1 -0
- package/dist/components/composer/Composer.js +238 -0
- package/dist/components/composer/Composer.js.map +1 -0
- package/dist/components/composer/helpers.d.ts +21 -0
- package/dist/components/composer/helpers.d.ts.map +1 -0
- package/dist/components/composer/helpers.js +75 -0
- package/dist/components/composer/helpers.js.map +1 -0
- package/dist/components/composer/index.d.ts +3 -0
- package/dist/components/composer/index.d.ts.map +1 -0
- package/dist/components/composer/index.js +19 -0
- package/dist/components/composer/index.js.map +1 -0
- package/dist/components/form/engine/CompactRow.d.ts.map +1 -1
- package/dist/components/form/engine/CompactRow.js +307 -110
- 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 +123 -106
- package/dist/components/form/engine/CompactToolbar.js.map +1 -1
- package/dist/components/form/engine/FormEngine.d.ts +107 -11
- package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
- package/dist/components/form/engine/FormEngine.js +618 -179
- package/dist/components/form/engine/FormEngine.js.map +1 -1
- package/dist/components/form/engine/compactRowContext.d.ts +9 -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 +7 -3
- package/dist/components/form/engine/compactRowStyles.d.ts.map +1 -1
- package/dist/components/form/engine/compactRowStyles.js +88 -51
- 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/compactToolbarContext.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 +63 -2
- package/dist/components/form/engine/readFirst.d.ts.map +1 -1
- package/dist/components/form/engine/readFirst.js +121 -6
- 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/engine/variants/VariantCalmTable.d.ts +6 -0
- package/dist/components/form/engine/variants/VariantCalmTable.d.ts.map +1 -0
- package/dist/components/form/engine/variants/VariantCalmTable.js +94 -0
- package/dist/components/form/engine/variants/VariantCalmTable.js.map +1 -0
- package/dist/components/form/engine/variants/VariantCards.d.ts +6 -0
- package/dist/components/form/engine/variants/VariantCards.d.ts.map +1 -0
- package/dist/components/form/engine/variants/VariantCards.js +80 -0
- package/dist/components/form/engine/variants/VariantCards.js.map +1 -0
- package/dist/components/form/engine/variants/VariantFocus.d.ts +7 -0
- package/dist/components/form/engine/variants/VariantFocus.d.ts.map +1 -0
- package/dist/components/form/engine/variants/VariantFocus.js +138 -0
- package/dist/components/form/engine/variants/VariantFocus.js.map +1 -0
- package/dist/components/form/engine/variants/VariantMinimal.d.ts +6 -0
- package/dist/components/form/engine/variants/VariantMinimal.d.ts.map +1 -0
- package/dist/components/form/engine/variants/VariantMinimal.js +73 -0
- package/dist/components/form/engine/variants/VariantMinimal.js.map +1 -0
- package/dist/components/form/engine/variants/focusDemo.d.ts +13 -0
- package/dist/components/form/engine/variants/focusDemo.d.ts.map +1 -0
- package/dist/components/form/engine/variants/focusDemo.js +139 -0
- package/dist/components/form/engine/variants/focusDemo.js.map +1 -0
- package/dist/components/form/engine/variants/variantModel.d.ts +70 -0
- package/dist/components/form/engine/variants/variantModel.d.ts.map +1 -0
- package/dist/components/form/engine/variants/variantModel.js +133 -0
- package/dist/components/form/engine/variants/variantModel.js.map +1 -0
- package/dist/components/form/engine/variants/variantParts.d.ts +79 -0
- package/dist/components/form/engine/variants/variantParts.d.ts.map +1 -0
- package/dist/components/form/engine/variants/variantParts.js +191 -0
- package/dist/components/form/engine/variants/variantParts.js.map +1 -0
- package/dist/components/form/expressions/builder/index.d.ts.map +1 -1
- package/dist/components/form/expressions/builder/index.js +13 -2
- package/dist/components/form/expressions/builder/index.js.map +1 -1
- package/dist/components/form/expressions/useExpressions.d.ts.map +1 -1
- package/dist/components/form/expressions/useExpressions.js +4 -1
- package/dist/components/form/expressions/useExpressions.js.map +1 -1
- 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 +2 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.d.ts.map +1 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.js +8 -26
- package/dist/components/form/fields/allowed-values/AllowedValues.js.map +1 -1
- package/dist/components/form/fields/auto/AutoFormField.d.ts +3 -0
- package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
- package/dist/components/form/fields/auto/AutoFormField.js +42 -8
- package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
- package/dist/components/form/fields/binary/Binary.d.ts +15 -0
- package/dist/components/form/fields/binary/Binary.d.ts.map +1 -0
- package/dist/components/form/fields/binary/Binary.js +74 -0
- package/dist/components/form/fields/binary/Binary.js.map +1 -0
- package/dist/components/form/fields/boolean/Boolean.js +1 -1
- package/dist/components/form/fields/boolean/Boolean.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 +5 -4
- package/dist/components/form/fields/multi-select/MultiSelectFormField.js.map +1 -1
- package/dist/components/form/fields/select/Select.d.ts.map +1 -1
- package/dist/components/form/fields/select/Select.js +29 -12
- package/dist/components/form/fields/select/Select.js.map +1 -1
- package/dist/components/form/fields/select/SelectCollection.d.ts +8 -2
- package/dist/components/form/fields/select/SelectCollection.d.ts.map +1 -1
- package/dist/components/form/fields/select/SelectCollection.js +52 -16
- package/dist/components/form/fields/select/SelectCollection.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/components/imageLightbox/ImageLightbox.d.ts +21 -0
- package/dist/components/imageLightbox/ImageLightbox.d.ts.map +1 -0
- package/dist/components/imageLightbox/ImageLightbox.js +169 -0
- package/dist/components/imageLightbox/ImageLightbox.js.map +1 -0
- package/dist/components/imageLightbox/index.d.ts +2 -0
- package/dist/components/imageLightbox/index.d.ts.map +1 -0
- package/dist/components/imageLightbox/index.js +18 -0
- package/dist/components/imageLightbox/index.js.map +1 -0
- package/dist/components/searchFilterBar/SearchFilterBar.d.ts +33 -0
- package/dist/components/searchFilterBar/SearchFilterBar.d.ts.map +1 -0
- package/dist/components/searchFilterBar/SearchFilterBar.js +76 -0
- package/dist/components/searchFilterBar/SearchFilterBar.js.map +1 -0
- package/dist/components/searchFilterBar/index.d.ts +2 -0
- package/dist/components/searchFilterBar/index.d.ts.map +1 -0
- package/dist/components/searchFilterBar/index.js +18 -0
- package/dist/components/searchFilterBar/index.js.map +1 -0
- package/dist/components/supportTicket/AttachmentChips.d.ts +10 -0
- package/dist/components/supportTicket/AttachmentChips.d.ts.map +1 -0
- package/dist/components/supportTicket/AttachmentChips.js +122 -0
- package/dist/components/supportTicket/AttachmentChips.js.map +1 -0
- package/dist/components/supportTicket/InterfaceReferenceTags.d.ts +43 -0
- package/dist/components/supportTicket/InterfaceReferenceTags.d.ts.map +1 -0
- package/dist/components/supportTicket/InterfaceReferenceTags.js +31 -0
- package/dist/components/supportTicket/InterfaceReferenceTags.js.map +1 -0
- package/dist/components/supportTicket/ReferencePicker.d.ts +87 -0
- package/dist/components/supportTicket/ReferencePicker.d.ts.map +1 -0
- package/dist/components/supportTicket/ReferencePicker.js +295 -0
- package/dist/components/supportTicket/ReferencePicker.js.map +1 -0
- package/dist/components/supportTicket/TicketHeader.d.ts +86 -0
- package/dist/components/supportTicket/TicketHeader.d.ts.map +1 -0
- package/dist/components/supportTicket/TicketHeader.js +149 -0
- package/dist/components/supportTicket/TicketHeader.js.map +1 -0
- package/dist/components/supportTicket/TicketMetaTags.d.ts +32 -0
- package/dist/components/supportTicket/TicketMetaTags.d.ts.map +1 -0
- package/dist/components/supportTicket/TicketMetaTags.js +21 -0
- package/dist/components/supportTicket/TicketMetaTags.js.map +1 -0
- package/dist/components/supportTicket/TicketReplyBox.d.ts +63 -0
- package/dist/components/supportTicket/TicketReplyBox.d.ts.map +1 -0
- package/dist/components/supportTicket/TicketReplyBox.js +115 -0
- package/dist/components/supportTicket/TicketReplyBox.js.map +1 -0
- package/dist/components/supportTicket/attachmentAccess.d.ts +37 -0
- package/dist/components/supportTicket/attachmentAccess.d.ts.map +1 -0
- package/dist/components/supportTicket/attachmentAccess.js +132 -0
- package/dist/components/supportTicket/attachmentAccess.js.map +1 -0
- package/dist/components/supportTicket/fileToAttachment.d.ts +9 -0
- package/dist/components/supportTicket/fileToAttachment.d.ts.map +1 -0
- package/dist/components/supportTicket/fileToAttachment.js +28 -0
- package/dist/components/supportTicket/fileToAttachment.js.map +1 -0
- package/dist/components/supportTicket/index.d.ts +11 -0
- package/dist/components/supportTicket/index.d.ts.map +1 -0
- package/dist/components/supportTicket/index.js +27 -0
- package/dist/components/supportTicket/index.js.map +1 -0
- package/dist/components/supportTicket/meta.d.ts +71 -0
- package/dist/components/supportTicket/meta.d.ts.map +1 -0
- package/dist/components/supportTicket/meta.js +115 -0
- package/dist/components/supportTicket/meta.js.map +1 -0
- package/dist/components/supportTicket/ticketModel.d.ts +102 -0
- package/dist/components/supportTicket/ticketModel.d.ts.map +1 -0
- package/dist/components/supportTicket/ticketModel.js +3 -0
- package/dist/components/supportTicket/ticketModel.js.map +1 -0
- package/dist/components/ticketReferences/TicketReferences.d.ts +52 -0
- package/dist/components/ticketReferences/TicketReferences.d.ts.map +1 -0
- package/dist/components/ticketReferences/TicketReferences.js +492 -0
- package/dist/components/ticketReferences/TicketReferences.js.map +1 -0
- package/dist/components/ticketReferences/index.d.ts +3 -0
- package/dist/components/ticketReferences/index.d.ts.map +1 -0
- package/dist/components/ticketReferences/index.js +6 -0
- package/dist/components/ticketReferences/index.js.map +1 -0
- package/dist/components/ticketThread/TicketThread.d.ts +57 -0
- package/dist/components/ticketThread/TicketThread.d.ts.map +1 -0
- package/dist/components/ticketThread/TicketThread.js +299 -0
- package/dist/components/ticketThread/TicketThread.js.map +1 -0
- package/dist/components/ticketThread/index.d.ts +3 -0
- package/dist/components/ticketThread/index.d.ts.map +1 -0
- package/dist/components/ticketThread/index.js +7 -0
- package/dist/components/ticketThread/index.js.map +1 -0
- package/dist/helpers/common.d.ts +5 -0
- package/dist/helpers/common.d.ts.map +1 -1
- package/dist/helpers/common.js +20 -1
- package/dist/helpers/common.js.map +1 -1
- package/dist/helpers/scrollbar.d.ts +2 -0
- package/dist/helpers/scrollbar.d.ts.map +1 -0
- package/dist/helpers/scrollbar.js +25 -0
- package/dist/helpers/scrollbar.js.map +1 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/providers/StorageProvider.d.ts +13 -0
- package/dist/providers/StorageProvider.d.ts.map +1 -1
- package/dist/providers/StorageProvider.js +29 -5
- package/dist/providers/StorageProvider.js.map +1 -1
- package/package.json +6 -5
- package/src/components/FocusedEditing/index.tsx +17 -2
- package/src/components/composer/Composer.stories.tsx +238 -0
- package/src/components/composer/Composer.tsx +545 -0
- package/src/components/composer/helpers.ts +74 -0
- package/src/components/composer/index.ts +2 -0
- package/src/components/dpqlEditor/DpqlEditor.stories.tsx +74 -2
- package/src/components/form/engine/CompactRow.tsx +561 -283
- package/src/components/form/engine/CompactToolbar.tsx +216 -182
- package/src/components/form/engine/FormEngine.stories.tsx +1736 -162
- package/src/components/form/engine/FormEngine.tsx +886 -170
- package/src/components/form/engine/FormEngineRemote.stories.tsx +377 -0
- package/src/components/form/engine/_structuredData/StructuredDataView.stories.tsx +8 -0
- package/src/components/form/engine/compactRowContext.ts +14 -0
- package/src/components/form/engine/compactRowStyles.ts +273 -146
- package/src/components/form/engine/compactToolbarContext.ts +1 -0
- package/src/components/form/engine/optionActions.ts +40 -0
- package/src/components/form/engine/readFirst.ts +169 -10
- package/src/components/form/engine/rendererTypes.ts +55 -0
- package/src/components/form/engine/variants/FormEngineVariants.stories.tsx +159 -0
- package/src/components/form/engine/variants/VariantCalmTable.tsx +242 -0
- package/src/components/form/engine/variants/VariantCards.tsx +212 -0
- package/src/components/form/engine/variants/VariantFocus.tsx +382 -0
- package/src/components/form/engine/variants/VariantMinimal.tsx +170 -0
- package/src/components/form/engine/variants/focusDemo.ts +145 -0
- package/src/components/form/engine/variants/variantModel.ts +216 -0
- package/src/components/form/engine/variants/variantParts.tsx +313 -0
- package/src/components/form/expressions/ExpressionField.stories.tsx +84 -2
- package/src/components/form/expressions/builder/ExpressionBuilder.stories.tsx +213 -19
- package/src/components/form/expressions/builder/index.tsx +12 -1
- package/src/components/form/expressions/useExpressions.ts +4 -1
- package/src/components/form/fields/Field.stories.tsx +40 -0
- package/src/components/form/fields/Field.tsx +10 -1
- package/src/components/form/fields/allowed-values/AllowedValues.tsx +13 -36
- package/src/components/form/fields/array/ArrayAutoField.stories.tsx +64 -0
- package/src/components/form/fields/auto/AutoFormField.stories.tsx +146 -2
- package/src/components/form/fields/auto/AutoFormField.tsx +42 -1
- package/src/components/form/fields/binary/Binary.stories.tsx +122 -0
- package/src/components/form/fields/binary/Binary.tsx +81 -0
- package/src/components/form/fields/boolean/Boolean.stories.tsx +58 -0
- package/src/components/form/fields/boolean/Boolean.tsx +1 -1
- package/src/components/form/fields/byte-size/ByteSize.stories.tsx +24 -0
- package/src/components/form/fields/color/Color.stories.tsx +30 -0
- package/src/components/form/fields/cron/Cron.stories.tsx +8 -0
- package/src/components/form/fields/date/Date.stories.tsx +22 -0
- package/src/components/form/fields/file/File.stories.tsx +48 -0
- package/src/components/form/fields/long-string/LongString.stories.tsx +24 -0
- package/src/components/form/fields/markdown/Markdown.stories.tsx +8 -0
- package/src/components/form/fields/multi-select/MultiSelectFormField.tsx +14 -10
- package/src/components/form/fields/number/Number.stories.tsx +31 -0
- package/src/components/form/fields/object/Object.stories.tsx +88 -0
- package/src/components/form/fields/radio-group/RadioGroup.stories.tsx +24 -0
- package/src/components/form/fields/rich-text/RichText.stories.tsx +23 -0
- package/src/components/form/fields/schema-definition/SchemaDefinitionField.stories.tsx +72 -0
- package/src/components/form/fields/select/Select.stories.tsx +108 -0
- package/src/components/form/fields/select/Select.tsx +38 -12
- package/src/components/form/fields/select/SelectCollection.tsx +78 -17
- package/src/components/form/fields/string/String.stories.tsx +16 -0
- package/src/components/form/fields/template/TemplateField.stories.tsx +160 -0
- package/src/components/form/fields/url/Url.stories.tsx +24 -0
- package/src/components/form/index.tsx +2 -0
- package/src/components/imageLightbox/ImageLightbox.stories.tsx +238 -0
- package/src/components/imageLightbox/ImageLightbox.tsx +236 -0
- package/src/components/imageLightbox/index.ts +1 -0
- package/src/components/log/Log.stories.tsx +96 -0
- package/src/components/menu/Menu.stories.tsx +54 -0
- package/src/components/qonsoleSmartInput/QonsoleSmartInput.stories.tsx +83 -37
- package/src/components/searchFilterBar/SearchFilterBar.tsx +131 -0
- package/src/components/searchFilterBar/index.ts +1 -0
- package/src/components/smartEditor/SmartEditor.stories.tsx +32 -0
- package/src/components/supportTicket/AttachmentChips.stories.tsx +171 -0
- package/src/components/supportTicket/AttachmentChips.tsx +147 -0
- package/src/components/supportTicket/InterfaceReferenceTags.stories.tsx +171 -0
- package/src/components/supportTicket/InterfaceReferenceTags.tsx +96 -0
- package/src/components/supportTicket/ReferencePicker.stories.tsx +519 -0
- package/src/components/supportTicket/ReferencePicker.tsx +563 -0
- package/src/components/supportTicket/TicketConversation.stories.tsx +121 -0
- package/src/components/supportTicket/TicketHeader.stories.tsx +183 -0
- package/src/components/supportTicket/TicketHeader.tsx +247 -0
- package/src/components/supportTicket/TicketMetaTags.stories.tsx +103 -0
- package/src/components/supportTicket/TicketMetaTags.tsx +85 -0
- package/src/components/supportTicket/TicketReplyBox.stories.tsx +351 -0
- package/src/components/supportTicket/TicketReplyBox.tsx +146 -0
- package/src/components/supportTicket/attachmentAccess.ts +97 -0
- package/src/components/supportTicket/fileToAttachment.ts +24 -0
- package/src/components/supportTicket/index.ts +10 -0
- package/src/components/supportTicket/meta.ts +185 -0
- package/src/components/supportTicket/ticketModel.ts +131 -0
- package/src/components/ticketReferences/TicketReferences.stories.tsx +315 -0
- package/src/components/ticketReferences/TicketReferences.tsx +886 -0
- package/src/components/ticketReferences/index.ts +2 -0
- package/src/components/ticketThread/TicketThread.stories.tsx +828 -0
- package/src/components/ticketThread/TicketThread.tsx +704 -0
- package/src/components/ticketThread/index.ts +6 -0
- package/src/helpers/common.ts +19 -0
- package/src/helpers/scrollbar.ts +32 -0
- package/src/hooks/useFetch/useFetch.stories.tsx +30 -0
- package/src/hooks/useStorage/useStorage.stories.tsx +82 -0
- package/src/hooks/useWebSocket/useWebsocket.stories.tsx +127 -1
- package/src/index.tsx +8 -1
- package/src/providers/StorageProvider.tsx +30 -4
- package/src/stores/currentUser/currentUser.stories.tsx +49 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { ReqoreControlGroup } from '@qoretechnologies/reqore';
|
|
2
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { expect, fn, userEvent, waitFor, within } from 'storybook/test';
|
|
5
|
+
|
|
6
|
+
import { StoryMeta } from '../../../../types';
|
|
7
|
+
import { ReqraftBinaryFormField } from './Binary';
|
|
8
|
+
|
|
9
|
+
const meta = {
|
|
10
|
+
component: ReqraftBinaryFormField,
|
|
11
|
+
title: 'Components/Form/Binary',
|
|
12
|
+
args: {
|
|
13
|
+
onChange: fn(),
|
|
14
|
+
'aria-label': 'Binary',
|
|
15
|
+
},
|
|
16
|
+
render(args) {
|
|
17
|
+
const [value, setValue] = useState(args.value);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<ReqoreControlGroup>
|
|
21
|
+
<ReqraftBinaryFormField
|
|
22
|
+
{...args}
|
|
23
|
+
value={value}
|
|
24
|
+
onChange={(value) => {
|
|
25
|
+
args.onChange?.(value);
|
|
26
|
+
setValue(value);
|
|
27
|
+
}}
|
|
28
|
+
/>
|
|
29
|
+
</ReqoreControlGroup>
|
|
30
|
+
);
|
|
31
|
+
},
|
|
32
|
+
} as StoryMeta<typeof ReqraftBinaryFormField>;
|
|
33
|
+
|
|
34
|
+
export default meta;
|
|
35
|
+
type Story = StoryObj<typeof meta>;
|
|
36
|
+
|
|
37
|
+
export const WithValue: Story = {
|
|
38
|
+
args: {
|
|
39
|
+
value: 'cGFzc3dvcmQ=',
|
|
40
|
+
},
|
|
41
|
+
parameters: {
|
|
42
|
+
docs: {
|
|
43
|
+
description: {
|
|
44
|
+
story:
|
|
45
|
+
'Renders the Binary field pre-populated with a base64 payload — the textarea shows the encoded string.',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
async play({ canvasElement }) {
|
|
50
|
+
const canvas = within(canvasElement);
|
|
51
|
+
const textarea = canvas.getByLabelText('Binary');
|
|
52
|
+
|
|
53
|
+
await expect(textarea).toBeInTheDocument();
|
|
54
|
+
await expect(textarea).toHaveValue('cGFzc3dvcmQ=');
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const TypingUpdatesValue: Story = {
|
|
59
|
+
parameters: {
|
|
60
|
+
docs: {
|
|
61
|
+
description: {
|
|
62
|
+
story:
|
|
63
|
+
'Renders the empty Binary field. Typing a base64 string into the textarea updates the value and fires onChange after the debounce.',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
async play({ canvasElement, args }) {
|
|
68
|
+
const canvas = within(canvasElement);
|
|
69
|
+
const textarea = canvas.getByLabelText('Binary');
|
|
70
|
+
|
|
71
|
+
await userEvent.type(textarea, 'YWJj');
|
|
72
|
+
await expect(textarea).toHaveValue('YWJj');
|
|
73
|
+
await waitFor(() => expect(args.onChange).toHaveBeenLastCalledWith('YWJj'), {
|
|
74
|
+
timeout: 500,
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const UploadEncodesFileAsBase64: Story = {
|
|
80
|
+
parameters: {
|
|
81
|
+
docs: {
|
|
82
|
+
description: {
|
|
83
|
+
story:
|
|
84
|
+
'Renders the Binary field with its file drop zone. Uploading a file encodes it as base64 (data-URL prefix stripped) and fires onChange with the encoded string.',
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
async play({ canvasElement, args }) {
|
|
89
|
+
const file = new File(['hello'], 'test.bin', { type: 'application/octet-stream' });
|
|
90
|
+
// the hidden file input rendered by the reused ReqraftFileFormField drop zone
|
|
91
|
+
const input = canvasElement.querySelector('input[type="file"]') as HTMLInputElement;
|
|
92
|
+
|
|
93
|
+
await expect(input).toBeInTheDocument();
|
|
94
|
+
await userEvent.upload(input, file);
|
|
95
|
+
|
|
96
|
+
// base64 of "hello" is "aGVsbG8="; the data: URL prefix must be stripped
|
|
97
|
+
await waitFor(() => expect(args.onChange).toHaveBeenLastCalledWith('aGVsbG8='), {
|
|
98
|
+
timeout: 1000,
|
|
99
|
+
});
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const Disabled: Story = {
|
|
104
|
+
args: {
|
|
105
|
+
value: 'cGFzc3dvcmQ=',
|
|
106
|
+
disabled: true,
|
|
107
|
+
},
|
|
108
|
+
parameters: {
|
|
109
|
+
docs: {
|
|
110
|
+
description: {
|
|
111
|
+
story:
|
|
112
|
+
'Renders the Binary field with a base64 value but disabled — the textarea is non-interactive.',
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
async play({ canvasElement }) {
|
|
117
|
+
const canvas = within(canvasElement);
|
|
118
|
+
const textarea = canvas.getByLabelText('Binary');
|
|
119
|
+
|
|
120
|
+
await expect(textarea).toBeDisabled();
|
|
121
|
+
},
|
|
122
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ReqoreControlGroup, ReqoreTextarea } from '@qoretechnologies/reqore';
|
|
2
|
+
import { IReqoreTextareaProps } from '@qoretechnologies/reqore/dist/components/Textarea';
|
|
3
|
+
import { ChangeEvent, memo, useCallback, useEffect, useState } from 'react';
|
|
4
|
+
import { useDebounce } from 'react-use';
|
|
5
|
+
import { IFileFormFieldValue, ReqraftFileFormField } from '../file/File';
|
|
6
|
+
|
|
7
|
+
export interface IReqraftBinaryFormFieldProps extends Omit<IReqoreTextareaProps, 'onChange' | 'value'> {
|
|
8
|
+
value?: string;
|
|
9
|
+
onChange?: (value: string) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Strip a `data:<mime-type>;base64,` prefix so the emitted value carries raw base64, matching the
|
|
14
|
+
* canonical binary wire form the Qorus server expects. `ReqraftFileFormField` reads uploads with
|
|
15
|
+
* `readAsDataURL`, so its `content` always carries that prefix.
|
|
16
|
+
*/
|
|
17
|
+
const stripDataUrlPrefix = (dataUrl: string): string => {
|
|
18
|
+
const commaIndex = dataUrl.indexOf(',');
|
|
19
|
+
return commaIndex === -1 ? dataUrl : dataUrl.slice(commaIndex + 1);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A field for binary values encoded as base64. The value can be typed or pasted directly into the
|
|
24
|
+
* textarea, or populated by uploading a file — the upload reuses {@link ReqraftFileFormField} (the
|
|
25
|
+
* shared Reqraft file picker / drop zone) rather than a bespoke dropzone; its data-URL content is
|
|
26
|
+
* decoded to raw base64 for the field value.
|
|
27
|
+
*/
|
|
28
|
+
export const ReqraftBinaryFormField = memo(
|
|
29
|
+
({ value, onChange, ...rest }: IReqraftBinaryFormFieldProps) => {
|
|
30
|
+
const [localValue, setLocalValue] = useState<string>(value ?? '');
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (value !== localValue) {
|
|
34
|
+
setLocalValue(value ?? '');
|
|
35
|
+
}
|
|
36
|
+
}, [value]);
|
|
37
|
+
|
|
38
|
+
useDebounce(
|
|
39
|
+
() => {
|
|
40
|
+
if (localValue !== value) {
|
|
41
|
+
onChange?.(localValue);
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
100,
|
|
45
|
+
[localValue, onChange]
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const handleChange = useCallback((event: ChangeEvent<HTMLTextAreaElement>): void => {
|
|
49
|
+
setLocalValue(event.target.value);
|
|
50
|
+
}, []);
|
|
51
|
+
|
|
52
|
+
const handleFileChange = useCallback(
|
|
53
|
+
(file?: IFileFormFieldValue) => {
|
|
54
|
+
const base64 = stripDataUrlPrefix(file?.content ?? '');
|
|
55
|
+
setLocalValue(base64);
|
|
56
|
+
onChange?.(base64);
|
|
57
|
+
},
|
|
58
|
+
[onChange]
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<ReqoreControlGroup vertical fluid>
|
|
63
|
+
<ReqoreTextarea
|
|
64
|
+
scaleWithContent
|
|
65
|
+
fluid
|
|
66
|
+
value={localValue}
|
|
67
|
+
onChange={handleChange}
|
|
68
|
+
onClearClick={() => {
|
|
69
|
+
setLocalValue('');
|
|
70
|
+
onChange?.('');
|
|
71
|
+
}}
|
|
72
|
+
placeholder='Base64-encoded binary value'
|
|
73
|
+
{...rest}
|
|
74
|
+
/>
|
|
75
|
+
<ReqraftFileFormField disabled={rest.disabled} onChange={handleFileChange} />
|
|
76
|
+
</ReqoreControlGroup>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
export default ReqraftBinaryFormField;
|
|
@@ -34,6 +34,14 @@ export const Checked: Story = {
|
|
|
34
34
|
args: {
|
|
35
35
|
checked: true,
|
|
36
36
|
},
|
|
37
|
+
parameters: {
|
|
38
|
+
docs: {
|
|
39
|
+
description: {
|
|
40
|
+
story:
|
|
41
|
+
'Renders the Boolean field in the checked state. Clicking the toggle flips it to unchecked and fires onChange with false.',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
37
45
|
async play({ canvasElement, args }) {
|
|
38
46
|
const canvas = within(canvasElement);
|
|
39
47
|
|
|
@@ -49,6 +57,14 @@ export const Unchecked: Story = {
|
|
|
49
57
|
args: {
|
|
50
58
|
checked: false,
|
|
51
59
|
},
|
|
60
|
+
parameters: {
|
|
61
|
+
docs: {
|
|
62
|
+
description: {
|
|
63
|
+
story:
|
|
64
|
+
'Renders the Boolean field in the unchecked state. Clicking the toggle flips it to checked and fires onChange with true.',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
52
68
|
async play({ canvasElement, args }) {
|
|
53
69
|
const canvas = within(canvasElement);
|
|
54
70
|
|
|
@@ -59,9 +75,51 @@ export const Unchecked: Story = {
|
|
|
59
75
|
},
|
|
60
76
|
};
|
|
61
77
|
|
|
78
|
+
export const Unset: Story = {
|
|
79
|
+
args: {
|
|
80
|
+
checked: undefined,
|
|
81
|
+
},
|
|
82
|
+
parameters: {
|
|
83
|
+
docs: {
|
|
84
|
+
description: {
|
|
85
|
+
story:
|
|
86
|
+
'Renders the Boolean field without a default choice. The switch remains visibly unset until the user explicitly chooses Yes or No.',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const UnsetSelectsYes: Story = {
|
|
93
|
+
args: {
|
|
94
|
+
checked: undefined,
|
|
95
|
+
},
|
|
96
|
+
parameters: {
|
|
97
|
+
docs: {
|
|
98
|
+
description: {
|
|
99
|
+
story:
|
|
100
|
+
'Verifies that an unset Boolean field saves the first explicit Yes selection instead of treating the missing value as No.',
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
async play({ canvasElement, args }) {
|
|
105
|
+
const canvas = within(canvasElement);
|
|
106
|
+
|
|
107
|
+
await userEvent.click(canvas.getByLabelText('Boolean'));
|
|
108
|
+
await expect(args.onChange).toHaveBeenLastCalledWith(true);
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
|
|
62
112
|
export const Disabled: Story = {
|
|
63
113
|
args: {
|
|
64
114
|
checked: true,
|
|
65
115
|
disabled: true,
|
|
66
116
|
},
|
|
117
|
+
parameters: {
|
|
118
|
+
docs: {
|
|
119
|
+
description: {
|
|
120
|
+
story:
|
|
121
|
+
'Renders the Boolean field checked and disabled — the toggle is visible but non-interactive.',
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
},
|
|
67
125
|
};
|
|
@@ -30,6 +30,14 @@ export default meta;
|
|
|
30
30
|
type Story = StoryObj<typeof meta>;
|
|
31
31
|
|
|
32
32
|
export const Default: Story = {
|
|
33
|
+
parameters: {
|
|
34
|
+
docs: {
|
|
35
|
+
description: {
|
|
36
|
+
story:
|
|
37
|
+
'Renders the ByteSize field with no value. Typing a number into the amount input fires onChange with the composed byte-size expression.',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
33
41
|
play: async ({ canvasElement, args }) => {
|
|
34
42
|
const canvas = within(canvasElement);
|
|
35
43
|
const input = canvas.getByLabelText('Byte size amount');
|
|
@@ -43,6 +51,14 @@ export const WithValue: Story = {
|
|
|
43
51
|
args: {
|
|
44
52
|
value: '512MiB',
|
|
45
53
|
},
|
|
54
|
+
parameters: {
|
|
55
|
+
docs: {
|
|
56
|
+
description: {
|
|
57
|
+
story:
|
|
58
|
+
'Renders the ByteSize field pre-populated with "512MiB" — the amount and unit are split across the number input and the MiB unit selector.',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
46
62
|
play: async ({ canvasElement }) => {
|
|
47
63
|
const canvas = within(canvasElement);
|
|
48
64
|
await expect(await canvas.findByDisplayValue('512')).toBeInTheDocument();
|
|
@@ -55,6 +71,14 @@ export const ReadOnly: Story = {
|
|
|
55
71
|
value: '512MiB',
|
|
56
72
|
readOnly: true,
|
|
57
73
|
},
|
|
74
|
+
parameters: {
|
|
75
|
+
docs: {
|
|
76
|
+
description: {
|
|
77
|
+
story:
|
|
78
|
+
'Renders the ByteSize field with "512MiB" in read-only mode — the amount input is marked readonly and rejects further edits.',
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
58
82
|
play: async ({ canvasElement }) => {
|
|
59
83
|
const canvas = within(canvasElement);
|
|
60
84
|
const input = await canvas.findByDisplayValue('512');
|
|
@@ -34,6 +34,14 @@ export const WithValue: Story = {
|
|
|
34
34
|
args: {
|
|
35
35
|
value: { r: 100, g: 149, b: 237, a: 1 },
|
|
36
36
|
},
|
|
37
|
+
parameters: {
|
|
38
|
+
docs: {
|
|
39
|
+
description: {
|
|
40
|
+
story:
|
|
41
|
+
'Renders the Color field with a cornflower-blue RGBA value pre-selected in the sketch picker.',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
37
45
|
async play({ canvasElement }) {
|
|
38
46
|
const picker = canvasElement.querySelector('.sketch-picker');
|
|
39
47
|
const colorPanel = canvasElement.querySelector('.saturation-white');
|
|
@@ -47,12 +55,26 @@ export const Red: Story = {
|
|
|
47
55
|
args: {
|
|
48
56
|
value: { r: 220, g: 53, b: 69, a: 1 },
|
|
49
57
|
},
|
|
58
|
+
parameters: {
|
|
59
|
+
docs: {
|
|
60
|
+
description: {
|
|
61
|
+
story: 'Renders the Color field with a red RGBA value pre-selected in the sketch picker.',
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
50
65
|
async play({ canvasElement }) {
|
|
51
66
|
await expect(canvasElement.querySelector('.sketch-picker')).toBeInTheDocument();
|
|
52
67
|
},
|
|
53
68
|
};
|
|
54
69
|
|
|
55
70
|
export const Empty: Story = {
|
|
71
|
+
parameters: {
|
|
72
|
+
docs: {
|
|
73
|
+
description: {
|
|
74
|
+
story: 'Renders the Color field with no value — the sketch picker mounts empty.',
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
56
78
|
async play({ canvasElement }) {
|
|
57
79
|
await expect(canvasElement.querySelector('.sketch-picker')).toBeInTheDocument();
|
|
58
80
|
},
|
|
@@ -63,6 +85,14 @@ export const Disabled: Story = {
|
|
|
63
85
|
value: { r: 100, g: 149, b: 237, a: 1 },
|
|
64
86
|
disabled: true,
|
|
65
87
|
},
|
|
88
|
+
parameters: {
|
|
89
|
+
docs: {
|
|
90
|
+
description: {
|
|
91
|
+
story:
|
|
92
|
+
'Renders the Color field with a value but disabled — the sketch picker is visible but non-interactive.',
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
66
96
|
async play({ canvasElement }) {
|
|
67
97
|
await expect(canvasElement.querySelector('.sketch-picker')).toBeInTheDocument();
|
|
68
98
|
},
|
|
@@ -39,6 +39,14 @@ export const Default: Story = {
|
|
|
39
39
|
'aria-label': label,
|
|
40
40
|
})),
|
|
41
41
|
},
|
|
42
|
+
parameters: {
|
|
43
|
+
docs: {
|
|
44
|
+
description: {
|
|
45
|
+
story:
|
|
46
|
+
'Renders the Cron field with a "1 1 1 1 1" schedule split across the Minute / Hour / Day / Month / Weekday inputs. Typing into a segment fires onChange with the recomposed expression; the clear button resets the value.',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
42
50
|
|
|
43
51
|
async play({ args, canvasElement }) {
|
|
44
52
|
const canvas = within(canvasElement);
|
|
@@ -30,6 +30,13 @@ export default meta;
|
|
|
30
30
|
type Story = StoryObj<typeof meta>;
|
|
31
31
|
|
|
32
32
|
export const Empty: Story = {
|
|
33
|
+
parameters: {
|
|
34
|
+
docs: {
|
|
35
|
+
description: {
|
|
36
|
+
story: 'Renders the Date field with no value — the input mounts empty.',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
},
|
|
33
40
|
async play({ canvasElement }) {
|
|
34
41
|
const input = canvasElement.querySelector('input');
|
|
35
42
|
await expect(input).toBeInTheDocument();
|
|
@@ -40,6 +47,14 @@ export const WithValue: Story = {
|
|
|
40
47
|
args: {
|
|
41
48
|
value: '2025-01-15',
|
|
42
49
|
},
|
|
50
|
+
parameters: {
|
|
51
|
+
docs: {
|
|
52
|
+
description: {
|
|
53
|
+
story:
|
|
54
|
+
'Renders the Date field pre-populated with 2025-01-15 — the input shows the initial value without firing onChange.',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
43
58
|
async play({ canvasElement, args }) {
|
|
44
59
|
const input = canvasElement.querySelector('input');
|
|
45
60
|
await expect(input).toBeInTheDocument();
|
|
@@ -52,4 +67,11 @@ export const Disabled: Story = {
|
|
|
52
67
|
value: '2025-06-01',
|
|
53
68
|
disabled: true,
|
|
54
69
|
},
|
|
70
|
+
parameters: {
|
|
71
|
+
docs: {
|
|
72
|
+
description: {
|
|
73
|
+
story: 'Renders the Date field with a value but disabled — the input is non-interactive.',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
55
77
|
};
|
|
@@ -30,6 +30,14 @@ export default meta;
|
|
|
30
30
|
type Story = StoryObj<typeof meta>;
|
|
31
31
|
|
|
32
32
|
export const Empty: Story = {
|
|
33
|
+
parameters: {
|
|
34
|
+
docs: {
|
|
35
|
+
description: {
|
|
36
|
+
story:
|
|
37
|
+
'Renders the File field with no value — the "Click or drop files here to upload" drop zone is visible.',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
33
41
|
async play({ canvasElement }) {
|
|
34
42
|
const canvas = within(canvasElement);
|
|
35
43
|
await expect(canvas.getByText('Click or drop files here to upload')).toBeInTheDocument();
|
|
@@ -44,6 +52,14 @@ export const WithValue: Story = {
|
|
|
44
52
|
size: 28736,
|
|
45
53
|
},
|
|
46
54
|
},
|
|
55
|
+
parameters: {
|
|
56
|
+
docs: {
|
|
57
|
+
description: {
|
|
58
|
+
story:
|
|
59
|
+
'Renders the File field pre-populated with a PDF value — the file name is displayed in place of the drop zone.',
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
47
63
|
async play({ canvasElement }) {
|
|
48
64
|
const canvas = within(canvasElement);
|
|
49
65
|
await expect(canvas.getByText('report.pdf')).toBeInTheDocument();
|
|
@@ -58,6 +74,14 @@ export const WithImageValue: Story = {
|
|
|
58
74
|
size: 1024,
|
|
59
75
|
},
|
|
60
76
|
},
|
|
77
|
+
parameters: {
|
|
78
|
+
docs: {
|
|
79
|
+
description: {
|
|
80
|
+
story:
|
|
81
|
+
'Renders the File field pre-populated with a PNG image value — the file name and an inline preview thumbnail are shown.',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
61
85
|
async play({ canvasElement }) {
|
|
62
86
|
const canvas = within(canvasElement);
|
|
63
87
|
await expect(canvas.getByText('photo.png')).toBeInTheDocument();
|
|
@@ -75,6 +99,14 @@ export const WithAcceptedExtensions: Story = {
|
|
|
75
99
|
},
|
|
76
100
|
},
|
|
77
101
|
},
|
|
102
|
+
parameters: {
|
|
103
|
+
docs: {
|
|
104
|
+
description: {
|
|
105
|
+
story:
|
|
106
|
+
'Renders the File field with an accept option limiting uploads to PNG, JPEG and PDF — the allowed extensions are listed below the drop zone.',
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
},
|
|
78
110
|
async play({ canvasElement }) {
|
|
79
111
|
const canvas = within(canvasElement);
|
|
80
112
|
await expect(canvas.getByText('Click or drop files here to upload')).toBeInTheDocument();
|
|
@@ -86,6 +118,14 @@ export const Multiple: Story = {
|
|
|
86
118
|
args: {
|
|
87
119
|
multiple: true,
|
|
88
120
|
},
|
|
121
|
+
parameters: {
|
|
122
|
+
docs: {
|
|
123
|
+
description: {
|
|
124
|
+
story:
|
|
125
|
+
'Renders the File field with multiple-selection enabled — the underlying input carries the multiple attribute and the drop zone stays visible after files are added.',
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
},
|
|
89
129
|
async play({ canvasElement }) {
|
|
90
130
|
const canvas = within(canvasElement);
|
|
91
131
|
await expect(canvas.getByText('Click or drop files here to upload')).toBeInTheDocument();
|
|
@@ -105,6 +145,14 @@ export const WithBuildTab: Story = {
|
|
|
105
145
|
content: { type: 'string', ui_type: 'string', display_name: 'Content', required: true },
|
|
106
146
|
},
|
|
107
147
|
},
|
|
148
|
+
parameters: {
|
|
149
|
+
docs: {
|
|
150
|
+
description: {
|
|
151
|
+
story:
|
|
152
|
+
'Renders the File field with an argSchema — a "Build a File" tab appears alongside the "Upload a File" drop zone so the user can synthesize a file from schema fields.',
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
},
|
|
108
156
|
async play({ canvasElement }) {
|
|
109
157
|
const canvas = within(canvasElement);
|
|
110
158
|
await expect(canvas.getByText('Upload a File')).toBeInTheDocument();
|
|
@@ -39,6 +39,14 @@ export const WithValue: Story = {
|
|
|
39
39
|
args: {
|
|
40
40
|
value: 'Hello world',
|
|
41
41
|
},
|
|
42
|
+
parameters: {
|
|
43
|
+
docs: {
|
|
44
|
+
description: {
|
|
45
|
+
story:
|
|
46
|
+
'Renders the LongString field pre-populated with "Hello world". Clicking clear empties the textarea and fires onChange; typing new content updates the value after the debounce.',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
42
50
|
async play({ canvasElement, args, step }) {
|
|
43
51
|
const canvas = within(canvasElement);
|
|
44
52
|
const textarea = canvas.getByLabelText('LongString');
|
|
@@ -66,6 +74,14 @@ export const WithValue: Story = {
|
|
|
66
74
|
};
|
|
67
75
|
|
|
68
76
|
export const Empty: Story = {
|
|
77
|
+
parameters: {
|
|
78
|
+
docs: {
|
|
79
|
+
description: {
|
|
80
|
+
story:
|
|
81
|
+
'Renders the LongString field with no value. Typing into the empty textarea updates the value and fires onChange after the debounce.',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
69
85
|
async play({ canvasElement, args }) {
|
|
70
86
|
const canvas = within(canvasElement);
|
|
71
87
|
const textarea = canvas.getByLabelText('LongString');
|
|
@@ -86,6 +102,14 @@ export const Disabled: Story = {
|
|
|
86
102
|
value: 'Cannot edit this',
|
|
87
103
|
disabled: true,
|
|
88
104
|
},
|
|
105
|
+
parameters: {
|
|
106
|
+
docs: {
|
|
107
|
+
description: {
|
|
108
|
+
story:
|
|
109
|
+
'Renders the LongString field with a value but disabled — the textarea shows the value and rejects further edits.',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
89
113
|
async play({ canvasElement }) {
|
|
90
114
|
const canvas = within(canvasElement);
|
|
91
115
|
const textarea = canvas.getByLabelText('LongString');
|
|
@@ -35,6 +35,14 @@ export const Default: Story = {
|
|
|
35
35
|
args: {
|
|
36
36
|
'aria-label': 'MarkdownEditor',
|
|
37
37
|
},
|
|
38
|
+
parameters: {
|
|
39
|
+
docs: {
|
|
40
|
+
description: {
|
|
41
|
+
story:
|
|
42
|
+
'Renders the Markdown field pre-populated with the sample markdown fixture — the editor and the live preview render side by side.',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
38
46
|
async play({ canvasElement, args }) {
|
|
39
47
|
const canvas = within(canvasElement);
|
|
40
48
|
const editor = canvas.getByLabelText('MarkdownEditor');
|
|
@@ -2,6 +2,7 @@ import { ReqoreMultiSelect } from '@qoretechnologies/reqore';
|
|
|
2
2
|
import { TReqoreMultiSelectItem } from '@qoretechnologies/reqore/dist/components/MultiSelect';
|
|
3
3
|
import { IQorusAllowedValue } from '@qoretechnologies/ts-toolkit';
|
|
4
4
|
import { memo, useMemo } from 'react';
|
|
5
|
+
import { getSelectItemShortDescription } from '../select/SelectCollection';
|
|
5
6
|
|
|
6
7
|
export interface IMultiSelectFormFieldProps {
|
|
7
8
|
/** Currently selected values (plain scalars) */
|
|
@@ -33,16 +34,19 @@ export const MultiSelectFormField = memo(
|
|
|
33
34
|
|
|
34
35
|
const reqoreItems = useMemo<TReqoreMultiSelectItem[]>(() => {
|
|
35
36
|
const base = items.map(
|
|
36
|
-
(item): TReqoreMultiSelectItem =>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
(item): TReqoreMultiSelectItem => {
|
|
38
|
+
const description = getSelectItemShortDescription(item);
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
value: item.value?.value as string,
|
|
42
|
+
label: item.display_name ?? String(item.value?.value ?? ''),
|
|
43
|
+
description,
|
|
44
|
+
wrap: true,
|
|
45
|
+
// IDE parity: when `*` is selected, every other item is disabled.
|
|
46
|
+
disabled:
|
|
47
|
+
!!item.disabled || (selectedValues.includes('*') && item.value?.value !== '*'),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
46
50
|
);
|
|
47
51
|
|
|
48
52
|
// IDE parity: selected values that aren't in the allowed list still
|
|
@@ -38,6 +38,14 @@ export const Integer: Story = {
|
|
|
38
38
|
value: 42,
|
|
39
39
|
type: 'int',
|
|
40
40
|
},
|
|
41
|
+
parameters: {
|
|
42
|
+
docs: {
|
|
43
|
+
description: {
|
|
44
|
+
story:
|
|
45
|
+
'Renders the Number field in integer mode with 42 pre-populated. Typing a new integer updates the value and fires onChange after the debounce.',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
41
49
|
async play({ args, canvasElement }) {
|
|
42
50
|
const canvas = within(canvasElement);
|
|
43
51
|
const input = canvas.getByLabelText('Number');
|
|
@@ -58,6 +66,14 @@ export const Float: Story = {
|
|
|
58
66
|
value: 3.14,
|
|
59
67
|
type: 'float',
|
|
60
68
|
},
|
|
69
|
+
parameters: {
|
|
70
|
+
docs: {
|
|
71
|
+
description: {
|
|
72
|
+
story:
|
|
73
|
+
'Renders the Number field in float mode with 3.14 pre-populated — the input uses a 0.1 step and accepts decimals.',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
61
77
|
async play({ args, canvasElement }) {
|
|
62
78
|
const canvas = within(canvasElement);
|
|
63
79
|
const input = canvas.getByLabelText('Number');
|
|
@@ -76,6 +92,13 @@ export const Empty: Story = {
|
|
|
76
92
|
args: {
|
|
77
93
|
type: 'int',
|
|
78
94
|
},
|
|
95
|
+
parameters: {
|
|
96
|
+
docs: {
|
|
97
|
+
description: {
|
|
98
|
+
story: 'Renders the Number field in integer mode with no value — the input mounts empty.',
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
79
102
|
async play({ canvasElement }) {
|
|
80
103
|
const canvas = within(canvasElement);
|
|
81
104
|
const input = canvas.getByLabelText('Number');
|
|
@@ -91,6 +114,14 @@ export const Disabled: Story = {
|
|
|
91
114
|
type: 'int',
|
|
92
115
|
disabled: true,
|
|
93
116
|
},
|
|
117
|
+
parameters: {
|
|
118
|
+
docs: {
|
|
119
|
+
description: {
|
|
120
|
+
story:
|
|
121
|
+
'Renders the Number field with a value but disabled — the input shows the value and rejects further edits.',
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
},
|
|
94
125
|
async play({ canvasElement }) {
|
|
95
126
|
const canvas = within(canvasElement);
|
|
96
127
|
const input = canvas.getByLabelText('Number');
|