@uva-glass/component-library 3.55.6 → 3.55.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Accordion-DvblEUVu.js.map +1 -1
- package/dist/AccordionCard-BXy-plB7.js.map +1 -1
- package/dist/ActionList-O9w1hqNg.js.map +1 -1
- package/dist/AddCatalogueLinkForm-rph4K9P0.js.map +1 -1
- package/dist/CheckboxButtonBar-5UMIFMKH.js.map +1 -1
- package/dist/ClipboardButton-geHjMl2J.js.map +1 -1
- package/dist/ControlsButton-B1XRpMUM.js.map +1 -1
- package/dist/CopyableText-DkyhZ6wk.js.map +1 -1
- package/dist/Drawer-e7UFHVg9.js.map +1 -1
- package/dist/EmptyStateDataDisplay-D0QiI8nE.js.map +1 -1
- package/dist/ExpandableInfoPanel-CnBVVNlJ.js.map +1 -1
- package/dist/FeedbackBar-ByKp32HE.js.map +1 -1
- package/dist/FieldHint-fxnEOsVZ.js.map +1 -1
- package/dist/Input-Bn-arMaC.js.map +1 -1
- package/dist/InputField-BWAy19w9.js.map +1 -1
- package/dist/Lexical.prod-CqPLSi0R.js.map +1 -1
- package/dist/LexicalClipboard.prod-BVw_sFpo.js.map +1 -1
- package/dist/LexicalComposerContext.prod-Ca-YN_fj.js.map +1 -1
- package/dist/LexicalExtension.prod-CUQTgbur.js.map +1 -1
- package/dist/LexicalLink.prod-DMhcqD9x.js.map +1 -1
- package/dist/LexicalList.prod-eYlcb5Ao.js.map +1 -1
- package/dist/LexicalTable.prod-DlOxUQou.js.map +1 -1
- package/dist/LexicalUtils.prod-BqcriFWV.js.map +1 -1
- package/dist/LinkContextMenu-ePn1iZ_z.js.map +1 -1
- package/dist/MenuLink-Cm1yZO_5.js.map +1 -1
- package/dist/ModalDialog-N50NGnd4.js.map +1 -1
- package/dist/MultiSelectBox-Cuh_o-A1.js.map +1 -1
- package/dist/MultiSelectItem-BF5xRjz5.js.map +1 -1
- package/dist/Notification-CIhsHuF0.js.map +1 -1
- package/dist/OverlayStepBar-CjaoYdsh.js.map +1 -1
- package/dist/PageOverlay-S4xsqJha.js.map +1 -1
- package/dist/PasteHandlerPlugin-BNp8ST0q.js.map +1 -1
- package/dist/Periods-BYETtB6R.js.map +1 -1
- package/dist/ProgrammeCard-76gG7ksx.js.map +1 -1
- package/dist/RadioGroup-JeTjVp5B.js.map +1 -1
- package/dist/Slider-BlLyrET9.js.map +1 -1
- package/dist/SortableProvider-8HYiBXJS.js.map +1 -1
- package/dist/Spinner-BpElTDIu.js.map +1 -1
- package/dist/StatusPill-DM7n3I4W.js.map +1 -1
- package/dist/TableCellContextMenu-D0IMQr3E.js.map +1 -1
- package/dist/TableCellResizerPlugin-Bc5y-Qbx.js.map +1 -1
- package/dist/TextArea-CuASC9bX.js.map +1 -1
- package/dist/ToggleSwitch-C7z7JVtx.js.map +1 -1
- package/dist/Tooltip-D27p9kh4.js.map +1 -1
- package/dist/VarIndicator-C-GueOZD.js.map +1 -1
- package/dist/assets/{src/css/fonts.css → fonts.css} +4 -4
- package/dist/chunk-SZQXB3JV-D6GR5B4F.js.map +1 -1
- package/dist/{client-8jeXrH7N.js → client-b7M3CmlC.js} +9 -9
- package/dist/{client-8jeXrH7N.js.map → client-b7M3CmlC.js.map} +1 -1
- package/dist/clsx-BD2qMUU1.js.map +1 -1
- package/dist/components/Accordion/Accordion.test.js +2 -2
- package/dist/components/Accordion/Accordion.test.js.map +1 -1
- package/dist/components/AccordionCard/AccordionCard.test.js +2 -2
- package/dist/components/AccordionCard/AccordionCard.test.js.map +1 -1
- package/dist/components/ActionList/ActionList.test.js +2 -2
- package/dist/components/ActionList/ActionList.test.js.map +1 -1
- package/dist/components/AppStatusBar/AppStatusBar.test.js +1 -1
- package/dist/components/AppStatusBar/AppStatusBar.test.js.map +1 -1
- package/dist/components/Attention/Attention.test.js +1 -1
- package/dist/components/Attention/Attention.test.js.map +1 -1
- package/dist/components/Backdrop/Backdrop.test.js +1 -1
- package/dist/components/Backdrop/Backdrop.test.js.map +1 -1
- package/dist/components/Buttons/Button.test.js +1 -1
- package/dist/components/Buttons/Button.test.js.map +1 -1
- package/dist/components/Buttons/LinkButton.test.js +1 -1
- package/dist/components/Buttons/LinkButton.test.js.map +1 -1
- package/dist/components/Buttons/MenuButton.js.map +1 -1
- package/dist/components/Buttons/MenuButton.test.js +1 -1
- package/dist/components/Buttons/MenuButton.test.js.map +1 -1
- package/dist/components/Card/Card.test.js +1 -1
- package/dist/components/Card/Card.test.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.test.js +2 -2
- package/dist/components/Checkbox/Checkbox.test.js.map +1 -1
- package/dist/components/CheckboxButtonBar/CheckboxButtonBar.test.js +1 -1
- package/dist/components/CheckboxButtonBar/CheckboxButtonBar.test.js.map +1 -1
- package/dist/components/CheckboxTree/CheckboxTree.stories.js.map +1 -1
- package/dist/components/Drawer/Drawer.stories.js.map +1 -1
- package/dist/components/FeedbackBar/FeedbackBar.stories.js.map +1 -1
- package/dist/components/FeedbackBar/FeedbackBar.test.js +1 -1
- package/dist/components/FeedbackBar/FeedbackBar.test.js.map +1 -1
- package/dist/components/Icon/Icon.js.map +1 -1
- package/dist/components/IconButton/IconButton.stories.js.map +1 -1
- package/dist/components/InputField/InputField.stories.js.map +1 -1
- package/dist/components/Label/Label.test.js +1 -1
- package/dist/components/Label/Label.test.js.map +1 -1
- package/dist/components/MetaDataBar/MetaDataBar.test.js +1 -1
- package/dist/components/MetaDataBar/MetaDataBar.test.js.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.stories.js.map +1 -1
- package/dist/components/MultiSelectBox/MultiSelectBox.stories.js.map +1 -1
- package/dist/components/MultiSelectBox/MultiSelectBox.test.js +1 -1
- package/dist/components/MultiSelectBox/MultiSelectBox.test.js.map +1 -1
- package/dist/components/Notification/Notification.test.js +1 -1
- package/dist/components/Notification/Notification.test.js.map +1 -1
- package/dist/components/OverlayStepBar/OverlayStepBar.stories.js.map +1 -1
- package/dist/components/PageOverlay/PageOverlay.stories.js +2 -2
- package/dist/components/PageOverlay/PageOverlay.stories.js.map +1 -1
- package/dist/components/RadioGroup/Radiogroup.test.js +1 -1
- package/dist/components/RadioGroup/Radiogroup.test.js.map +1 -1
- package/dist/components/RteEditor/Plugins/BlockFormatPlugin/BlockFormatPlugin.js.map +1 -1
- package/dist/components/RteEditor/Plugins/CourseCataloguePlugin/CourseCataloguePlugin.js.map +1 -1
- package/dist/components/RteEditor/Plugins/ListPlugin/ListPlugin.js.map +1 -1
- package/dist/components/RteEditor/Plugins/TablePlugin/helpers.js.map +1 -1
- package/dist/components/RteEditor/Providers/LanguageProvider.js.map +1 -1
- package/dist/components/RteEditor/RteEditor.stories.js.map +1 -1
- package/dist/components/RteEditor/helpers.js.map +1 -1
- package/dist/components/RteEditor/hooks/useFlyout.js.map +1 -1
- package/dist/components/RteEditor/hooks/useTranslation.js.map +1 -1
- package/dist/components/RteEditor/nodes/CourseCatalogueNode/CourseCatalogueNode.js.map +1 -1
- package/dist/components/RteEditor/nodes/TableWrapperNode/TableWrapperNode.js.map +1 -1
- package/dist/components/SearchField/SearchField.js.map +1 -1
- package/dist/components/SearchField/SearcheField.stories.js.map +1 -1
- package/dist/components/SearchField/components/ResultsOption.js.map +1 -1
- package/dist/components/SelectListbox/SelectListBox.stories.js.map +1 -1
- package/dist/components/SelectListbox/SelectListbox.js.map +1 -1
- package/dist/components/SelectListbox/SelectProvider.js.map +1 -1
- package/dist/components/SelectListbox/components/SelectButton.js.map +1 -1
- package/dist/components/SelectListbox/components/SelectContainer.js.map +1 -1
- package/dist/components/SelectListbox/components/SelectOption.js.map +1 -1
- package/dist/components/SelectListbox/components/SelectOptionBox.js.map +1 -1
- package/dist/components/Slider/Slider.stories.js.map +1 -1
- package/dist/components/Sortable/Sortable.js.map +1 -1
- package/dist/components/Sortable/components/SortableHandle.js.map +1 -1
- package/dist/components/Sortable/components/SortableItem.js.map +1 -1
- package/dist/components/Sortable/sortableReducer.js.map +1 -1
- package/dist/components/StatusBadge/StatusBadge.test.js +1 -1
- package/dist/components/StatusBadge/StatusBadge.test.js.map +1 -1
- package/dist/components/TextArea/TextArea.test.js +2 -2
- package/dist/components/TextArea/TextArea.test.js.map +1 -1
- package/dist/components/VarIndicator/VarIndicator.test.js +2 -2
- package/dist/components/VarIndicator/VarIndicator.test.js.map +1 -1
- package/dist/components/WeekSelector/WeekSelector.js.map +1 -1
- package/dist/components/WeekSelector/WeekSelector.stories.js.map +1 -1
- package/dist/components/WeekSelector/components/WeekSelectorOption.js.map +1 -1
- package/dist/components/hooks/useDebounce.js.map +1 -1
- package/dist/components/hooks/useOnClickOutside.js.map +1 -1
- package/dist/components/hooks/usePositionedFloaters.js.map +1 -1
- package/dist/components/hooks/useResponsive.js.map +1 -1
- package/dist/components-BzxAULjf.js.map +1 -1
- package/dist/dist-V_v3kC0L.js.map +1 -1
- package/dist/{esm-BwHoYxVb.js → esm-BoujHjK5.js} +2 -2
- package/dist/{esm-BwHoYxVb.js.map → esm-BoujHjK5.js.map} +1 -1
- package/dist/helpers-B1VK8xTF.js.map +1 -1
- package/dist/lib-BvOQt8El.js.map +1 -1
- package/dist/{react-18-B7MZmX_Z.js → react-18-DxAWL8_m.js} +2 -2
- package/dist/{react-18-B7MZmX_Z.js.map → react-18-DxAWL8_m.js.map} +1 -1
- package/dist/{react.esm-D_F72rY1.js → react.esm-CweFe1CK.js} +2 -2
- package/dist/{react.esm-D_F72rY1.js.map → react.esm-CweFe1CK.js.map} +1 -1
- package/dist/setupTests.js +2 -2
- package/dist/setupTests.js.map +1 -1
- package/dist/storybook__react.d.js +1 -1
- package/dist/storybook__react.d.js.map +1 -1
- package/dist/test-Pa9Lwbsq.js.map +1 -1
- package/dist/test-utils-Cmn06m_x.js.map +1 -1
- package/package.json +7 -6
- /package/dist/assets/favicon/{src/assets/favicon/android-chrome-192x192.png → android-chrome-192x192.png} +0 -0
- /package/dist/assets/favicon/{src/assets/favicon/android-chrome-512x512.png → android-chrome-512x512.png} +0 -0
- /package/dist/assets/favicon/{src/assets/favicon/apple-touch-icon.png → apple-touch-icon.png} +0 -0
- /package/dist/assets/favicon/{src/assets/favicon/favicon-16x16.png → favicon-16x16.png} +0 -0
- /package/dist/assets/favicon/{src/assets/favicon/favicon-32x32.png → favicon-32x32.png} +0 -0
- /package/dist/assets/favicon/{src/assets/favicon/favicon.ico → favicon.ico} +0 -0
- /package/dist/assets/favicon/{src/assets/favicon/favicon.svg → favicon.svg} +0 -0
- /package/dist/assets/favicon/{src/assets/favicon/site.webmanifest → site.webmanifest} +0 -0
- /package/dist/assets/fonts/{src/assets/fonts/SourceSans3-Regular.otf.woff → SourceSans3-Regular.otf.woff} +0 -0
- /package/dist/assets/fonts/{src/assets/fonts/SourceSans3-Regular.otf.woff2 → SourceSans3-Regular.otf.woff2} +0 -0
- /package/dist/assets/fonts/{src/assets/fonts/SourceSans3-Semibold.otf.woff → SourceSans3-Semibold.otf.woff} +0 -0
- /package/dist/assets/fonts/{src/assets/fonts/SourceSans3-Semibold.otf.woff2 → SourceSans3-Semibold.otf.woff2} +0 -0
- /package/dist/assets/{src/css/globals.css → globals.css} +0 -0
- /package/dist/assets/{src/css/variables.css → variables.css} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MetaDataBar.test.js","names":[],"sources":["../../../src/components/MetaDataBar/MetaDataBar.test.tsx"],"sourcesContent":["import { render, screen } from '@testing-library/react';\n\nimport type { IconProps } from 'components/Icon';\n\nimport { MetaDataBar } from './MetaDataBar';\n\njest.mock('components/Icon', () => ({\n Icon: ({ name }: { name: IconProps['name'] }) => <span data-testid=\"icon\">{name}</span>,\n}));\n\nconst mockItemData = [\n { iconName: 'AcademicCap' as IconProps['name'], itemLabel: 'Jedi Academy' },\n { iconName: 'User' as IconProps['name'], itemLabel: 'Luuk Hemelwandelaar' },\n];\n\ndescribe('MetaDataBar', () => {\n it('renders correctly with content items', () => {\n render(<MetaDataBar itemData={mockItemData} />);\n\n expect(screen.getByText('AcademicCap')).toBeInTheDocument();\n expect(screen.getByText('Jedi Academy')).toBeInTheDocument();\n expect(screen.getByText('User')).toBeInTheDocument();\n expect(screen.getByText('Luuk Hemelwandelaar')).toBeInTheDocument();\n\n expect(screen.getAllByTestId('icon')).toHaveLength(mockItemData.length);\n });\n\n it('renders nothing when content is empty', () => {\n render(<MetaDataBar itemData={[]} />);\n expect(screen.queryByTestId('icon')).not.toBeInTheDocument();\n expect(screen.queryByText(/.+/)).not.toBeInTheDocument();\n });\n});\n"],"mappings":";;;;AAMA,KAAK,KAAK,0BAA0B,EAClC,OAAO,EAAE,cAAwC,kBAAC,QAAD;CAAM,eAAY;WAAQ;CAAY,CAAA,EACxF,EAAE;AAEH,IAAM,IAAe,CACnB;CAAE,UAAU;CAAoC,WAAW;CAAgB,EAC3E;CAAE,UAAU;CAA6B,WAAW;CAAuB,CAC5E;AAED,SAAS,qBAAqB;
|
|
1
|
+
{"version":3,"file":"MetaDataBar.test.js","names":[],"sources":["../../../src/components/MetaDataBar/MetaDataBar.test.tsx"],"sourcesContent":["import { render, screen } from '@testing-library/react';\n\nimport type { IconProps } from 'components/Icon';\n\nimport { MetaDataBar } from './MetaDataBar';\n\njest.mock('components/Icon', () => ({\n Icon: ({ name }: { name: IconProps['name'] }) => <span data-testid=\"icon\">{name}</span>,\n}));\n\nconst mockItemData = [\n { iconName: 'AcademicCap' as IconProps['name'], itemLabel: 'Jedi Academy' },\n { iconName: 'User' as IconProps['name'], itemLabel: 'Luuk Hemelwandelaar' },\n];\n\ndescribe('MetaDataBar', () => {\n it('renders correctly with content items', () => {\n render(<MetaDataBar itemData={mockItemData} />);\n\n expect(screen.getByText('AcademicCap')).toBeInTheDocument();\n expect(screen.getByText('Jedi Academy')).toBeInTheDocument();\n expect(screen.getByText('User')).toBeInTheDocument();\n expect(screen.getByText('Luuk Hemelwandelaar')).toBeInTheDocument();\n\n expect(screen.getAllByTestId('icon')).toHaveLength(mockItemData.length);\n });\n\n it('renders nothing when content is empty', () => {\n render(<MetaDataBar itemData={[]} />);\n expect(screen.queryByTestId('icon')).not.toBeInTheDocument();\n expect(screen.queryByText(/.+/)).not.toBeInTheDocument();\n });\n});\n"],"mappings":";;;;AAMA,KAAK,KAAK,0BAA0B,EAClC,OAAO,EAAE,cAAwC,kBAAC,QAAD;CAAM,eAAY;WAAQ;CAAY,CAAA,EACxF,EAAE;AAEH,IAAM,IAAe,CACnB;CAAE,UAAU;CAAoC,WAAW;CAAgB,EAC3E;CAAE,UAAU;CAA6B,WAAW;CAAuB,CAC5E;AAED,SAAS,qBAAqB;CAY5B,AAXA,GAAG,8CAA8C;EAQ/C,AAPA,EAAO,kBAAC,GAAD,EAAa,UAAU,GAAgB,CAAA,CAAC,EAE/C,OAAO,EAAO,UAAU,cAAc,CAAC,CAAC,mBAAmB,EAC3D,OAAO,EAAO,UAAU,eAAe,CAAC,CAAC,mBAAmB,EAC5D,OAAO,EAAO,UAAU,OAAO,CAAC,CAAC,mBAAmB,EACpD,OAAO,EAAO,UAAU,sBAAsB,CAAC,CAAC,mBAAmB,EAEnE,OAAO,EAAO,eAAe,OAAO,CAAC,CAAC,aAAa,EAAa,OAAO;GACvE,EAEF,GAAG,+CAA+C;EAGhD,AAFA,EAAO,kBAAC,GAAD,EAAa,UAAU,EAAE,EAAI,CAAA,CAAC,EACrC,OAAO,EAAO,cAAc,OAAO,CAAC,CAAC,IAAI,mBAAmB,EAC5D,OAAO,EAAO,YAAY,KAAK,CAAC,CAAC,IAAI,mBAAmB;GACxD;EACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiSelect.stories.js","names":[],"sources":["../../../src/components/MultiSelect/MultiSelect.stories.tsx"],"sourcesContent":["import { fn } from 'storybook/test';\nimport { useState } from 'react';\n\nimport type { ChangeEvent, PropsWithChildren } from 'react';\nimport type { Meta, StoryFn } from '@storybook/react';\nimport type { MultiSelectProps } from './MultiSelect';\n\nimport { MultiSelect } from './MultiSelect';\n\nimport { Container } from 'storyComponents/Container';\n\nconst codeString = `\n // MultiSelectHeader can be added optionally\n <MultiSelect.MultiSelectHeader label={label} clearTrigger={clearTrigger} onClear={handleClear} />\n <MultiSelect noBorder={noBorder} scrollable={scrollable}>\n {mockItems.map(({ itemName, itemValue, disabled }) => (\n <MultiSelect.MultiSelectItem key={itemName} label={itemName} value={itemValue}\n checked={stateItems.includes(itemValue)} onChange={handleChange} disabled={disabled} />\n ))}\n </MultiSelect>\n `;\n\n// eslint-disable-next-line import/no-default-export\nexport default {\n title: 'Organisms/MultiSelect',\n component: MultiSelect,\n argTypes: {\n header: {\n table: {\n disable: true,\n },\n },\n },\n parameters: {\n inspectComponent: MultiSelect,\n codeString: codeString,\n },\n} as Meta<PropsWithChildren<MultiSelectProps>>;\n\nconst Template: StoryFn<PropsWithChildren<MultiSelectProps>> = (args) => {\n const [items, setItems] = useState<string[]>([]);\n\n const mockItems = [\n { itemName: 'AItem 1', itemValue: '1', disabled: true },\n { itemName: 'BItem 2', itemValue: '2' },\n { itemName: 'Multi line Item 3 Item 3 Item 3 Item 3 Item 3 Item 3 Item 3 Item 3 Item 3 Item 3', itemValue: '3' },\n { itemName: 'CItem 4', itemValue: '4' },\n { itemName: 'DItem 5', itemValue: '5' },\n { itemName: 'EItem 6', itemValue: '6' },\n ];\n\n const handleClear = () => {\n setItems([]);\n fn()();\n };\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n const { checked, value } = event.target;\n setItems((prevState) => {\n const newItems = checked ? [...prevState, value] : prevState.filter((itemValue) => itemValue !== value);\n fn()(newItems);\n return newItems;\n });\n };\n\n return (\n <Container>\n {/* header added under separate boolean arg here for storybook purpose, \n it should be added as direct arg to MultiSelect when used in application */}\n {args.header && (\n <MultiSelect.MultiSelectHeader\n label=\"Item list\"\n clearTrigger={items.length > 0 ? 'Clear Selection' : ''}\n onClear={handleClear}\n />\n )}\n <MultiSelect {...args}>\n {mockItems.map(({ itemName, itemValue, disabled }) => (\n <MultiSelect.MultiSelectItem\n key={itemName}\n label={itemName}\n value={itemValue}\n checked={items.includes(itemValue)}\n onChange={handleChange}\n disabled={disabled}\n />\n ))}\n </MultiSelect>\n </Container>\n );\n};\n\nconst defaultArgs: Partial<MultiSelectProps> = {\n scrollable: true,\n noBorder: false,\n};\n\nexport const MultiSelectExample = Template.bind({});\nMultiSelectExample.args = {\n ...defaultArgs,\n};\n\nexport const WithHeader = Template.bind({});\nWithHeader.args = {\n ...defaultArgs,\n // boolean is not normal way of adding header but if added after template the rerender logic of\n // storybook would not correctly clear the checkboxes\n header: true,\n};\n\nexport const WithheaderAndWithoutScrollContainerAndBorder = Template.bind({});\nWithheaderAndWithoutScrollContainerAndBorder.args = {\n scrollable: false,\n noBorder: true,\n // boolean is not normal way of adding header but if added after template the rerender logic of\n // storybook would not correctly clear the checkboxes\n header: true,\n};\n"],"mappings":";;;;;;AAuBA,IAAA,IAAe;CACb,OAAO;CACP,WAAW;CACX,UAAU,EACR,QAAQ,EACN,OAAO,EACL,SAAS,IACV,EACF,EACF;CACD,YAAY;EACV,kBAAkB;EACN;EACb;CACF,EAEK,KAA0D,MAAS;CACvE,IAAM,CAAC,GAAO,KAAY,EAAmB,EAAE,CAAC,EAE1C,IAAY;EAChB;GAAE,UAAU;GAAW,WAAW;GAAK,UAAU;GAAM;EACvD;GAAE,UAAU;GAAW,WAAW;GAAK;EACvC;GAAE,UAAU;GAAoF,WAAW;GAAK;EAChH;GAAE,UAAU;GAAW,WAAW;GAAK;EACvC;GAAE,UAAU;GAAW,WAAW;GAAK;EACvC;GAAE,UAAU;GAAW,WAAW;GAAK;EACxC,EAEK,UAAoB;
|
|
1
|
+
{"version":3,"file":"MultiSelect.stories.js","names":[],"sources":["../../../src/components/MultiSelect/MultiSelect.stories.tsx"],"sourcesContent":["import { fn } from 'storybook/test';\nimport { useState } from 'react';\n\nimport type { ChangeEvent, PropsWithChildren } from 'react';\nimport type { Meta, StoryFn } from '@storybook/react';\nimport type { MultiSelectProps } from './MultiSelect';\n\nimport { MultiSelect } from './MultiSelect';\n\nimport { Container } from 'storyComponents/Container';\n\nconst codeString = `\n // MultiSelectHeader can be added optionally\n <MultiSelect.MultiSelectHeader label={label} clearTrigger={clearTrigger} onClear={handleClear} />\n <MultiSelect noBorder={noBorder} scrollable={scrollable}>\n {mockItems.map(({ itemName, itemValue, disabled }) => (\n <MultiSelect.MultiSelectItem key={itemName} label={itemName} value={itemValue}\n checked={stateItems.includes(itemValue)} onChange={handleChange} disabled={disabled} />\n ))}\n </MultiSelect>\n `;\n\n// eslint-disable-next-line import/no-default-export\nexport default {\n title: 'Organisms/MultiSelect',\n component: MultiSelect,\n argTypes: {\n header: {\n table: {\n disable: true,\n },\n },\n },\n parameters: {\n inspectComponent: MultiSelect,\n codeString: codeString,\n },\n} as Meta<PropsWithChildren<MultiSelectProps>>;\n\nconst Template: StoryFn<PropsWithChildren<MultiSelectProps>> = (args) => {\n const [items, setItems] = useState<string[]>([]);\n\n const mockItems = [\n { itemName: 'AItem 1', itemValue: '1', disabled: true },\n { itemName: 'BItem 2', itemValue: '2' },\n { itemName: 'Multi line Item 3 Item 3 Item 3 Item 3 Item 3 Item 3 Item 3 Item 3 Item 3 Item 3', itemValue: '3' },\n { itemName: 'CItem 4', itemValue: '4' },\n { itemName: 'DItem 5', itemValue: '5' },\n { itemName: 'EItem 6', itemValue: '6' },\n ];\n\n const handleClear = () => {\n setItems([]);\n fn()();\n };\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n const { checked, value } = event.target;\n setItems((prevState) => {\n const newItems = checked ? [...prevState, value] : prevState.filter((itemValue) => itemValue !== value);\n fn()(newItems);\n return newItems;\n });\n };\n\n return (\n <Container>\n {/* header added under separate boolean arg here for storybook purpose, \n it should be added as direct arg to MultiSelect when used in application */}\n {args.header && (\n <MultiSelect.MultiSelectHeader\n label=\"Item list\"\n clearTrigger={items.length > 0 ? 'Clear Selection' : ''}\n onClear={handleClear}\n />\n )}\n <MultiSelect {...args}>\n {mockItems.map(({ itemName, itemValue, disabled }) => (\n <MultiSelect.MultiSelectItem\n key={itemName}\n label={itemName}\n value={itemValue}\n checked={items.includes(itemValue)}\n onChange={handleChange}\n disabled={disabled}\n />\n ))}\n </MultiSelect>\n </Container>\n );\n};\n\nconst defaultArgs: Partial<MultiSelectProps> = {\n scrollable: true,\n noBorder: false,\n};\n\nexport const MultiSelectExample = Template.bind({});\nMultiSelectExample.args = {\n ...defaultArgs,\n};\n\nexport const WithHeader = Template.bind({});\nWithHeader.args = {\n ...defaultArgs,\n // boolean is not normal way of adding header but if added after template the rerender logic of\n // storybook would not correctly clear the checkboxes\n header: true,\n};\n\nexport const WithheaderAndWithoutScrollContainerAndBorder = Template.bind({});\nWithheaderAndWithoutScrollContainerAndBorder.args = {\n scrollable: false,\n noBorder: true,\n // boolean is not normal way of adding header but if added after template the rerender logic of\n // storybook would not correctly clear the checkboxes\n header: true,\n};\n"],"mappings":";;;;;;AAuBA,IAAA,IAAe;CACb,OAAO;CACP,WAAW;CACX,UAAU,EACR,QAAQ,EACN,OAAO,EACL,SAAS,IACV,EACF,EACF;CACD,YAAY;EACV,kBAAkB;EACN;EACb;CACF,EAEK,KAA0D,MAAS;CACvE,IAAM,CAAC,GAAO,KAAY,EAAmB,EAAE,CAAC,EAE1C,IAAY;EAChB;GAAE,UAAU;GAAW,WAAW;GAAK,UAAU;GAAM;EACvD;GAAE,UAAU;GAAW,WAAW;GAAK;EACvC;GAAE,UAAU;GAAoF,WAAW;GAAK;EAChH;GAAE,UAAU;GAAW,WAAW;GAAK;EACvC;GAAE,UAAU;GAAW,WAAW;GAAK;EACvC;GAAE,UAAU;GAAW,WAAW;GAAK;EACxC,EAEK,UAAoB;EAExB,AADA,EAAS,EAAE,CAAC,EACZ,GAAI,EAAE;IAGF,KAAgB,MAAyC;EAC7D,IAAM,EAAE,YAAS,aAAU,EAAM;EACjC,GAAU,MAAc;GACtB,IAAM,IAAW,IAAU,CAAC,GAAG,GAAW,EAAM,GAAG,EAAU,QAAQ,MAAc,MAAc,EAAM;GAEvG,OADA,GAAI,CAAC,EAAS,EACP;IACP;;CAGJ,OACE,kBAAC,GAAD,EAAA,UAAA,CAGG,EAAK,UACJ,kBAAC,EAAY,mBAAb;EACE,OAAM;EACN,cAAc,EAAM,SAAS,IAAI,oBAAoB;EACrD,SAAS;EACT,CAAA,EAEJ,kBAAC,GAAD;EAAa,GAAI;YACd,EAAU,KAAK,EAAE,aAAU,cAAW,kBACrC,kBAAC,EAAY,iBAAb;GAEE,OAAO;GACP,OAAO;GACP,SAAS,EAAM,SAAS,EAAU;GAClC,UAAU;GACA;GACV,EANK,EAML,CACF;EACU,CAAA,CACJ,EAAA,CAAA;GAIV,IAAyC;CAC7C,YAAY;CACZ,UAAU;CACX,EAEY,IAAqB,EAAS,KAAK,EAAE,CAAC;AACnD,EAAmB,OAAO,EACxB,GAAG,GACJ;AAED,IAAa,IAAa,EAAS,KAAK,EAAE,CAAC;AAC3C,EAAW,OAAO;CAChB,GAAG;CAGH,QAAQ;CACT;AAED,IAAa,IAA+C,EAAS,KAAK,EAAE,CAAC;AAC7E,EAA6C,OAAO;CAClD,YAAY;CACZ,UAAU;CAGV,QAAQ;CACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiSelectBox.stories.js","names":[],"sources":["../../../src/components/MultiSelectBox/MultiSelectBox.stories.tsx"],"sourcesContent":["import { fn } from 'storybook/test';\nimport { useState } from 'react';\n\nimport type { Meta, StoryFn } from '@storybook/react';\nimport type { MultiSelectBoxProps, MultiSelectData } from './MultiSelectBox';\n\nimport { MultiSelectBox } from './MultiSelectBox';\n\nconst codeString = `<MultiSelectBox selectData={[{label, value}]} onChange={fn} labelSuffix={string} />`;\n\n// eslint-disable-next-line import/no-default-export\nexport default {\n title: 'Organisms/MultiSelectBox',\n component: MultiSelectBox,\n argTypes: {\n onChange: {\n action: 'Selected values',\n table: {\n disable: true,\n },\n },\n },\n parameters: {\n inspectComponent: MultiSelectBox,\n codeString: codeString,\n },\n} as Meta<MultiSelectBoxProps>;\n\nconst mockItems = [\n { label: 'A.B. Docent', value: '1' },\n { label: 'B.C. Docent met lange achternaam', value: '2' },\n {\n label: 'prof. F.G. Docent met lang achternaam',\n value: '3',\n },\n { label: 'H.I. Docent', value: '4' },\n { label: 'K.L. Docent ', value: '5' },\n { label: 'A.B. Docent', value: '6' },\n { label: 'B.C. Docent met lange achternaam', value: '7' },\n {\n label: 'prof. F.G. Docent met lang achternaam',\n value: '8',\n },\n { label: 'H.I. Docent', value: '9' },\n { label: 'K.L. Docent ', value: '10' },\n];\n\nconst Template: StoryFn<MultiSelectBoxProps> = (args) => {\n const [selectedItems, setSelectedItems] = useState<MultiSelectData[]>(args.defaultSelectedItems || []);\n\n const handleChange = (items: MultiSelectData[]) => {\n if (args.onChange) {\n args.onChange(items);\n }\n setSelectedItems(items);\n };\n\n return (\n <div style={{ width: '30rem', margin: '0rem auto 0 auto' }}>\n <span>{selectedItems.map((item) => item.label).join(', ')}</span>\n <MultiSelectBox {...args} onChange={handleChange} />\n </div>\n );\n};\n\nconst defaultArgs: Partial<MultiSelectBoxProps> = {\n fullWidth: false,\n labelSuffix: 'geselecteerd',\n maxOptionHeight: '20rem',\n optionPositionRight: false,\n disabled: false,\n selectData: mockItems,\n onChange: fn(),\n};\n\nexport const MultiSelectBoxExample = Template.bind({});\nMultiSelectBoxExample.args = {\n ...defaultArgs,\n};\n\nexport const WithDefaultSelectedItems = Template.bind({});\nWithDefaultSelectedItems.args = {\n ...defaultArgs,\n defaultSelectedItems: [\n { label: 'A.B. Docent', value: '1' },\n { label: 'H.I. Docent', value: '4' },\n { label: 'A.B. Docent', value: '6' },\n ],\n};\n"],"mappings":";;;;AAWA,IAAA,IAAe;CACb,OAAO;CACP,WAAW;CACX,UAAU,EACR,UAAU;EACR,QAAQ;EACR,OAAO,EACL,SAAS,IACV;EACF,EACF;CACD,YAAY;EACV,kBAAkB;EACN;EACb;CACF,EAEK,IAAY;CAChB;EAAE,OAAO;EAAe,OAAO;EAAK;CACpC;EAAE,OAAO;EAAoC,OAAO;EAAK;CACzD;EACE,OAAO;EACP,OAAO;EACR;CACD;EAAE,OAAO;EAAe,OAAO;EAAK;CACpC;EAAE,OAAO;EAAgB,OAAO;EAAK;CACrC;EAAE,OAAO;EAAe,OAAO;EAAK;CACpC;EAAE,OAAO;EAAoC,OAAO;EAAK;CACzD;EACE,OAAO;EACP,OAAO;EACR;CACD;EAAE,OAAO;EAAe,OAAO;EAAK;CACpC;EAAE,OAAO;EAAgB,OAAO;EAAM;CACvC,EAEK,KAA0C,MAAS;CACvD,IAAM,CAAC,GAAe,KAAoB,EAA4B,EAAK,wBAAwB,EAAE,CAAC,EAEhG,KAAgB,MAA6B;
|
|
1
|
+
{"version":3,"file":"MultiSelectBox.stories.js","names":[],"sources":["../../../src/components/MultiSelectBox/MultiSelectBox.stories.tsx"],"sourcesContent":["import { fn } from 'storybook/test';\nimport { useState } from 'react';\n\nimport type { Meta, StoryFn } from '@storybook/react';\nimport type { MultiSelectBoxProps, MultiSelectData } from './MultiSelectBox';\n\nimport { MultiSelectBox } from './MultiSelectBox';\n\nconst codeString = `<MultiSelectBox selectData={[{label, value}]} onChange={fn} labelSuffix={string} />`;\n\n// eslint-disable-next-line import/no-default-export\nexport default {\n title: 'Organisms/MultiSelectBox',\n component: MultiSelectBox,\n argTypes: {\n onChange: {\n action: 'Selected values',\n table: {\n disable: true,\n },\n },\n },\n parameters: {\n inspectComponent: MultiSelectBox,\n codeString: codeString,\n },\n} as Meta<MultiSelectBoxProps>;\n\nconst mockItems = [\n { label: 'A.B. Docent', value: '1' },\n { label: 'B.C. Docent met lange achternaam', value: '2' },\n {\n label: 'prof. F.G. Docent met lang achternaam',\n value: '3',\n },\n { label: 'H.I. Docent', value: '4' },\n { label: 'K.L. Docent ', value: '5' },\n { label: 'A.B. Docent', value: '6' },\n { label: 'B.C. Docent met lange achternaam', value: '7' },\n {\n label: 'prof. F.G. Docent met lang achternaam',\n value: '8',\n },\n { label: 'H.I. Docent', value: '9' },\n { label: 'K.L. Docent ', value: '10' },\n];\n\nconst Template: StoryFn<MultiSelectBoxProps> = (args) => {\n const [selectedItems, setSelectedItems] = useState<MultiSelectData[]>(args.defaultSelectedItems || []);\n\n const handleChange = (items: MultiSelectData[]) => {\n if (args.onChange) {\n args.onChange(items);\n }\n setSelectedItems(items);\n };\n\n return (\n <div style={{ width: '30rem', margin: '0rem auto 0 auto' }}>\n <span>{selectedItems.map((item) => item.label).join(', ')}</span>\n <MultiSelectBox {...args} onChange={handleChange} />\n </div>\n );\n};\n\nconst defaultArgs: Partial<MultiSelectBoxProps> = {\n fullWidth: false,\n labelSuffix: 'geselecteerd',\n maxOptionHeight: '20rem',\n optionPositionRight: false,\n disabled: false,\n selectData: mockItems,\n onChange: fn(),\n};\n\nexport const MultiSelectBoxExample = Template.bind({});\nMultiSelectBoxExample.args = {\n ...defaultArgs,\n};\n\nexport const WithDefaultSelectedItems = Template.bind({});\nWithDefaultSelectedItems.args = {\n ...defaultArgs,\n defaultSelectedItems: [\n { label: 'A.B. Docent', value: '1' },\n { label: 'H.I. Docent', value: '4' },\n { label: 'A.B. Docent', value: '6' },\n ],\n};\n"],"mappings":";;;;AAWA,IAAA,IAAe;CACb,OAAO;CACP,WAAW;CACX,UAAU,EACR,UAAU;EACR,QAAQ;EACR,OAAO,EACL,SAAS,IACV;EACF,EACF;CACD,YAAY;EACV,kBAAkB;EACN;EACb;CACF,EAEK,IAAY;CAChB;EAAE,OAAO;EAAe,OAAO;EAAK;CACpC;EAAE,OAAO;EAAoC,OAAO;EAAK;CACzD;EACE,OAAO;EACP,OAAO;EACR;CACD;EAAE,OAAO;EAAe,OAAO;EAAK;CACpC;EAAE,OAAO;EAAgB,OAAO;EAAK;CACrC;EAAE,OAAO;EAAe,OAAO;EAAK;CACpC;EAAE,OAAO;EAAoC,OAAO;EAAK;CACzD;EACE,OAAO;EACP,OAAO;EACR;CACD;EAAE,OAAO;EAAe,OAAO;EAAK;CACpC;EAAE,OAAO;EAAgB,OAAO;EAAM;CACvC,EAEK,KAA0C,MAAS;CACvD,IAAM,CAAC,GAAe,KAAoB,EAA4B,EAAK,wBAAwB,EAAE,CAAC,EAEhG,KAAgB,MAA6B;EAIjD,AAHI,EAAK,YACP,EAAK,SAAS,EAAM,EAEtB,EAAiB,EAAM;;CAGzB,OACE,kBAAC,OAAD;EAAK,OAAO;GAAE,OAAO;GAAS,QAAQ;GAAoB;YAA1D,CACE,kBAAC,QAAD,EAAA,UAAO,EAAc,KAAK,MAAS,EAAK,MAAM,CAAC,KAAK,KAAK,EAAQ,CAAA,EACjE,kBAAC,GAAD;GAAgB,GAAI;GAAM,UAAU;GAAgB,CAAA,CAChD;;GAIJ,IAA4C;CAChD,WAAW;CACX,aAAa;CACb,iBAAiB;CACjB,qBAAqB;CACrB,UAAU;CACV,YAAY;CACZ,UAAU,GAAI;CACf,EAEY,IAAwB,EAAS,KAAK,EAAE,CAAC;AACtD,EAAsB,OAAO,EAC3B,GAAG,GACJ;AAED,IAAa,IAA2B,EAAS,KAAK,EAAE,CAAC;AACzD,EAAyB,OAAO;CAC9B,GAAG;CACH,sBAAsB;EACpB;GAAE,OAAO;GAAe,OAAO;GAAK;EACpC;GAAE,OAAO;GAAe,OAAO;GAAK;EACpC;GAAE,OAAO;GAAe,OAAO;GAAK;EACrC;CACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../../dist-V_v3kC0L.js";
|
|
2
2
|
import { t as e } from "../../MultiSelectBox-Cuh_o-A1.js";
|
|
3
|
-
import { i as t, n, t as r } from "../../react.esm-
|
|
3
|
+
import { i as t, n, t as r } from "../../react.esm-CweFe1CK.js";
|
|
4
4
|
import { Fragment as i, jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/MultiSelectBox/MultiSelectBox.test.tsx
|
|
6
6
|
var s = jest.fn(), c = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiSelectBox.test.js","names":[],"sources":["../../../src/components/MultiSelectBox/MultiSelectBox.test.tsx"],"sourcesContent":["import '@testing-library/jest-dom';\nimport { render, screen, fireEvent } from '@testing-library/react';\n\nimport { MultiSelectBox } from './MultiSelectBox';\n\nconst onChangeSpy = jest.fn();\n\nconst mockSelectData = [\n { label: 'Option 1', value: '1' },\n { label: 'Option 2', value: '2' },\n { label: 'Option 3', value: '3' },\n];\n\ndescribe('MultiSelectBox', () => {\n it('renders the component with default props', () => {\n render(<MultiSelectBox selectData={mockSelectData} onChange={onChangeSpy} labelSuffix=\"selected\" />);\n const button = screen.getByRole('button');\n expect(button).toBeInTheDocument();\n expect(button).toHaveAttribute('aria-expanded', 'false');\n });\n\n it('opens the dropdown when the button is clicked', () => {\n render(<MultiSelectBox selectData={mockSelectData} onChange={onChangeSpy} labelSuffix=\"selected\" />);\n const button = screen.getByRole('button');\n fireEvent.click(button);\n expect(button).toHaveAttribute('aria-expanded', 'true');\n expect(screen.getByRole('listbox')).toBeInTheDocument();\n });\n\n it('closes the dropdown when clicking outside', () => {\n render(\n <>\n <MultiSelectBox selectData={mockSelectData} onChange={onChangeSpy} labelSuffix=\"selected\" />\n <div data-testid=\"outside-element\">Outside</div>\n </>\n );\n\n const button = screen.getByRole('button');\n fireEvent.click(button);\n expect(button).toHaveAttribute('aria-expanded', 'true');\n const outsideElement = screen.getByTestId('outside-element');\n fireEvent.click(outsideElement);\n expect(button).toHaveAttribute('aria-expanded', 'false');\n });\n});\n"],"mappings":";;;;;AAKA,IAAM,IAAc,KAAK,IAAI,EAEvB,IAAiB;CACrB;EAAE,OAAO;EAAY,OAAO;EAAK;CACjC;EAAE,OAAO;EAAY,OAAO;EAAK;CACjC;EAAE,OAAO;EAAY,OAAO;EAAK;CAClC;AAED,SAAS,wBAAwB;
|
|
1
|
+
{"version":3,"file":"MultiSelectBox.test.js","names":[],"sources":["../../../src/components/MultiSelectBox/MultiSelectBox.test.tsx"],"sourcesContent":["import '@testing-library/jest-dom';\nimport { render, screen, fireEvent } from '@testing-library/react';\n\nimport { MultiSelectBox } from './MultiSelectBox';\n\nconst onChangeSpy = jest.fn();\n\nconst mockSelectData = [\n { label: 'Option 1', value: '1' },\n { label: 'Option 2', value: '2' },\n { label: 'Option 3', value: '3' },\n];\n\ndescribe('MultiSelectBox', () => {\n it('renders the component with default props', () => {\n render(<MultiSelectBox selectData={mockSelectData} onChange={onChangeSpy} labelSuffix=\"selected\" />);\n const button = screen.getByRole('button');\n expect(button).toBeInTheDocument();\n expect(button).toHaveAttribute('aria-expanded', 'false');\n });\n\n it('opens the dropdown when the button is clicked', () => {\n render(<MultiSelectBox selectData={mockSelectData} onChange={onChangeSpy} labelSuffix=\"selected\" />);\n const button = screen.getByRole('button');\n fireEvent.click(button);\n expect(button).toHaveAttribute('aria-expanded', 'true');\n expect(screen.getByRole('listbox')).toBeInTheDocument();\n });\n\n it('closes the dropdown when clicking outside', () => {\n render(\n <>\n <MultiSelectBox selectData={mockSelectData} onChange={onChangeSpy} labelSuffix=\"selected\" />\n <div data-testid=\"outside-element\">Outside</div>\n </>\n );\n\n const button = screen.getByRole('button');\n fireEvent.click(button);\n expect(button).toHaveAttribute('aria-expanded', 'true');\n const outsideElement = screen.getByTestId('outside-element');\n fireEvent.click(outsideElement);\n expect(button).toHaveAttribute('aria-expanded', 'false');\n });\n});\n"],"mappings":";;;;;AAKA,IAAM,IAAc,KAAK,IAAI,EAEvB,IAAiB;CACrB;EAAE,OAAO;EAAY,OAAO;EAAK;CACjC;EAAE,OAAO;EAAY,OAAO;EAAK;CACjC;EAAE,OAAO;EAAY,OAAO;EAAK;CAClC;AAED,SAAS,wBAAwB;CAgB/B,AAfA,GAAG,kDAAkD;EACnD,EAAO,kBAAC,GAAD;GAAgB,YAAY;GAAgB,UAAU;GAAa,aAAY;GAAa,CAAA,CAAC;EACpG,IAAM,IAAS,EAAO,UAAU,SAAS;EAEzC,AADA,OAAO,EAAO,CAAC,mBAAmB,EAClC,OAAO,EAAO,CAAC,gBAAgB,iBAAiB,QAAQ;GACxD,EAEF,GAAG,uDAAuD;EACxD,EAAO,kBAAC,GAAD;GAAgB,YAAY;GAAgB,UAAU;GAAa,aAAY;GAAa,CAAA,CAAC;EACpG,IAAM,IAAS,EAAO,UAAU,SAAS;EAGzC,AAFA,EAAU,MAAM,EAAO,EACvB,OAAO,EAAO,CAAC,gBAAgB,iBAAiB,OAAO,EACvD,OAAO,EAAO,UAAU,UAAU,CAAC,CAAC,mBAAmB;GACvD,EAEF,GAAG,mDAAmD;EACpD,EACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;GAAgB,YAAY;GAAgB,UAAU;GAAa,aAAY;GAAa,CAAA,EAC5F,kBAAC,OAAD;GAAK,eAAY;aAAkB;GAAa,CAAA,CAC/C,EAAA,CAAA,CACJ;EAED,IAAM,IAAS,EAAO,UAAU,SAAS;EAEzC,AADA,EAAU,MAAM,EAAO,EACvB,OAAO,EAAO,CAAC,gBAAgB,iBAAiB,OAAO;EACvD,IAAM,IAAiB,EAAO,YAAY,kBAAkB;EAE5D,AADA,EAAU,MAAM,EAAe,EAC/B,OAAO,EAAO,CAAC,gBAAgB,iBAAiB,QAAQ;GACxD;EACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../../dist-V_v3kC0L.js";
|
|
2
2
|
import { t as e } from "../../Notification-CIhsHuF0.js";
|
|
3
|
-
import { i as t, n } from "../../react.esm-
|
|
3
|
+
import { i as t, n } from "../../react.esm-CweFe1CK.js";
|
|
4
4
|
import { jsx as r } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/Notification/Notification.test.tsx
|
|
6
6
|
describe("Notification", () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Notification.test.js","names":[],"sources":["../../../src/components/Notification/Notification.test.tsx"],"sourcesContent":["import '@testing-library/jest-dom';\nimport { render, screen } from '@testing-library/react';\n\nimport { Notification } from './Notification';\n\ndescribe('Notification', () => {\n it('renders title and subtitle', () => {\n render(<Notification level=\"information\" title=\"Info title\" subtitle=\"Info subtitle\" />);\n expect(screen.getByText('Info title')).toBeInTheDocument();\n expect(screen.getByText('Info subtitle')).toBeInTheDocument();\n });\n\n it('renders bar variant', () => {\n render(<Notification level=\"danger\" variant=\"bar\" title=\"Danger title\" />);\n expect(screen.getByText('Danger title')).toBeInTheDocument();\n });\n});\n"],"mappings":";;;;;AAKA,SAAS,sBAAsB;
|
|
1
|
+
{"version":3,"file":"Notification.test.js","names":[],"sources":["../../../src/components/Notification/Notification.test.tsx"],"sourcesContent":["import '@testing-library/jest-dom';\nimport { render, screen } from '@testing-library/react';\n\nimport { Notification } from './Notification';\n\ndescribe('Notification', () => {\n it('renders title and subtitle', () => {\n render(<Notification level=\"information\" title=\"Info title\" subtitle=\"Info subtitle\" />);\n expect(screen.getByText('Info title')).toBeInTheDocument();\n expect(screen.getByText('Info subtitle')).toBeInTheDocument();\n });\n\n it('renders bar variant', () => {\n render(<Notification level=\"danger\" variant=\"bar\" title=\"Danger title\" />);\n expect(screen.getByText('Danger title')).toBeInTheDocument();\n });\n});\n"],"mappings":";;;;;AAKA,SAAS,sBAAsB;CAO7B,AANA,GAAG,oCAAoC;EAGrC,AAFA,EAAO,kBAAC,GAAD;GAAc,OAAM;GAAc,OAAM;GAAa,UAAS;GAAkB,CAAA,CAAC,EACxF,OAAO,EAAO,UAAU,aAAa,CAAC,CAAC,mBAAmB,EAC1D,OAAO,EAAO,UAAU,gBAAgB,CAAC,CAAC,mBAAmB;GAC7D,EAEF,GAAG,6BAA6B;EAE9B,AADA,EAAO,kBAAC,GAAD;GAAc,OAAM;GAAS,SAAQ;GAAM,OAAM;GAAiB,CAAA,CAAC,EAC1E,OAAO,EAAO,UAAU,eAAe,CAAC,CAAC,mBAAmB;GAC5D;EACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverlayStepBar.stories.js","names":[],"sources":["../../../src/components/OverlayStepBar/OverlayStepBar.stories.tsx"],"sourcesContent":["import { useState } from 'react';\n\nimport type { Meta, StoryFn } from '@storybook/react';\nimport type { OverlayStepBarProps } from './OverlayStepBar';\n\nimport { OverlayStepBar } from './OverlayStepBar';\n\nconst codeString =\n '<OverlayStepBar stepLabels={[string]} activeStep={number} disabledCountPrefix={[numbers]} onStepClick={(step) => void}/>';\n\n// eslint-disable-next-line import/no-default-export\nexport default {\n title: 'Molecules/OverlayStepBar',\n component: OverlayStepBar,\n argTypes: {\n activeStep: { control: 'number' },\n stepLabels: { control: 'object' },\n disabledCountPrefix: {\n table: {\n disable: true,\n },\n },\n onStepClick: { action: 'stepClicked' },\n },\n parameters: {\n inspectComponent: OverlayStepBar,\n codeString: codeString,\n },\n} as Meta<OverlayStepBarProps>;\n\nconst Template: StoryFn<OverlayStepBarProps> = (args) => {\n const [activeStep, setActiveStep] = useState(args.activeStep || 1);\n\n return (\n <OverlayStepBar\n {...args}\n activeStep={activeStep}\n onStepClick={(step) => {\n setActiveStep(step);\n args.onStepClick?.(step);\n }}\n />\n );\n};\n\nconst defaultArgs: Partial<OverlayStepBarProps> = {\n stepLabels: ['Basic Details', 'Lecturers', 'Period Planning', 'Assessment', 'Miscellaneous', 'Overview'],\n};\n\nexport const OverlayStepBarExample = Template.bind({});\nOverlayStepBarExample.args = {\n ...defaultArgs,\n activeStep: 2,\n};\n\nexport const OverlayStepBarHidePrifix = Template.bind({});\nOverlayStepBarHidePrifix.args = {\n ...defaultArgs,\n // eslint-disable-next-line @typescript-eslint/no-magic-numbers\n disabledCountPrefix: [1, 6],\n activeStep: 2,\n};\n"],"mappings":";;;AAWA,IAAA,IAAe;CACb,OAAO;CACP,WAAW;CACX,UAAU;EACR,YAAY,EAAE,SAAS,UAAU;EACjC,YAAY,EAAE,SAAS,UAAU;EACjC,qBAAqB,EACnB,OAAO,EACL,SAAS,IACV,EACF;EACD,aAAa,EAAE,QAAQ,eAAe;EACvC;CACD,YAAY;EACV,kBAAkB;EACN;EACb;CACF,EAEK,KAA0C,MAAS;CACvD,IAAM,CAAC,GAAY,KAAiB,EAAS,EAAK,cAAc,EAAE;
|
|
1
|
+
{"version":3,"file":"OverlayStepBar.stories.js","names":[],"sources":["../../../src/components/OverlayStepBar/OverlayStepBar.stories.tsx"],"sourcesContent":["import { useState } from 'react';\n\nimport type { Meta, StoryFn } from '@storybook/react';\nimport type { OverlayStepBarProps } from './OverlayStepBar';\n\nimport { OverlayStepBar } from './OverlayStepBar';\n\nconst codeString =\n '<OverlayStepBar stepLabels={[string]} activeStep={number} disabledCountPrefix={[numbers]} onStepClick={(step) => void}/>';\n\n// eslint-disable-next-line import/no-default-export\nexport default {\n title: 'Molecules/OverlayStepBar',\n component: OverlayStepBar,\n argTypes: {\n activeStep: { control: 'number' },\n stepLabels: { control: 'object' },\n disabledCountPrefix: {\n table: {\n disable: true,\n },\n },\n onStepClick: { action: 'stepClicked' },\n },\n parameters: {\n inspectComponent: OverlayStepBar,\n codeString: codeString,\n },\n} as Meta<OverlayStepBarProps>;\n\nconst Template: StoryFn<OverlayStepBarProps> = (args) => {\n const [activeStep, setActiveStep] = useState(args.activeStep || 1);\n\n return (\n <OverlayStepBar\n {...args}\n activeStep={activeStep}\n onStepClick={(step) => {\n setActiveStep(step);\n args.onStepClick?.(step);\n }}\n />\n );\n};\n\nconst defaultArgs: Partial<OverlayStepBarProps> = {\n stepLabels: ['Basic Details', 'Lecturers', 'Period Planning', 'Assessment', 'Miscellaneous', 'Overview'],\n};\n\nexport const OverlayStepBarExample = Template.bind({});\nOverlayStepBarExample.args = {\n ...defaultArgs,\n activeStep: 2,\n};\n\nexport const OverlayStepBarHidePrifix = Template.bind({});\nOverlayStepBarHidePrifix.args = {\n ...defaultArgs,\n // eslint-disable-next-line @typescript-eslint/no-magic-numbers\n disabledCountPrefix: [1, 6],\n activeStep: 2,\n};\n"],"mappings":";;;AAWA,IAAA,IAAe;CACb,OAAO;CACP,WAAW;CACX,UAAU;EACR,YAAY,EAAE,SAAS,UAAU;EACjC,YAAY,EAAE,SAAS,UAAU;EACjC,qBAAqB,EACnB,OAAO,EACL,SAAS,IACV,EACF;EACD,aAAa,EAAE,QAAQ,eAAe;EACvC;CACD,YAAY;EACV,kBAAkB;EACN;EACb;CACF,EAEK,KAA0C,MAAS;CACvD,IAAM,CAAC,GAAY,KAAiB,EAAS,EAAK,cAAc,EAAE;CAElE,OACE,kBAAC,GAAD;EACE,GAAI;EACQ;EACZ,cAAc,MAAS;GAErB,AADA,EAAc,EAAK,EACnB,EAAK,cAAc,EAAK;;EAE1B,CAAA;GAIA,IAA4C,EAChD,YAAY;CAAC;CAAiB;CAAa;CAAmB;CAAc;CAAiB;CAAW,EACzG,EAEY,IAAwB,EAAS,KAAK,EAAE,CAAC;AACtD,EAAsB,OAAO;CAC3B,GAAG;CACH,YAAY;CACb;AAED,IAAa,IAA2B,EAAS,KAAK,EAAE,CAAC;AACzD,EAAyB,OAAO;CAC9B,GAAG;CAEH,qBAAqB,CAAC,GAAG,EAAE;CAC3B,YAAY;CACb"}
|
|
@@ -7,7 +7,7 @@ import { t as a } from "../../PageOverlay-S4xsqJha.js";
|
|
|
7
7
|
import o, { useCallback as s, useEffect as c, useReducer as l, useRef as u, useState as d } from "react";
|
|
8
8
|
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
9
9
|
import { OverlayProvider as m } from "@react-aria/overlays";
|
|
10
|
-
//#region node_modules
|
|
10
|
+
//#region node_modules/react-stately/dist/private/utils/useControlledState.mjs
|
|
11
11
|
var h = typeof document < "u" ? o.useInsertionEffect ?? o.useLayoutEffect : () => {};
|
|
12
12
|
function g(e, t, n) {
|
|
13
13
|
let [r, i] = d(e || t), a = u(r), o = u(e !== void 0), f = e !== void 0;
|
|
@@ -26,7 +26,7 @@ function g(e, t, n) {
|
|
|
26
26
|
}, [n])];
|
|
27
27
|
}
|
|
28
28
|
//#endregion
|
|
29
|
-
//#region node_modules
|
|
29
|
+
//#region node_modules/react-stately/dist/private/overlays/useOverlayTriggerState.mjs
|
|
30
30
|
function _(e) {
|
|
31
31
|
let [t, n] = g(e.isOpen, e.defaultOpen || !1, e.onOpenChange);
|
|
32
32
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageOverlay.stories.js","names":["$3whtM$react","$3whtM$useState","$3whtM$useRef","$3whtM$useEffect","$3whtM$useReducer","$3whtM$useCallback","$hnMvi$useControlledState","$hnMvi$useCallback"],"sources":["../../../node_modules/@react-stately/utils/dist/useControlledState.mjs","../../../node_modules/@react-stately/overlays/dist/useOverlayTriggerState.mjs","../../../src/components/PageOverlay/PageOverlay.stories.tsx"],"sourcesContent":["import $3whtM$react, {useState as $3whtM$useState, useRef as $3whtM$useRef, useEffect as $3whtM$useEffect, useReducer as $3whtM$useReducer, useCallback as $3whtM$useCallback} from \"react\";\n\n/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */ \nvar $458b0a5536c1a7cf$var$_React_useInsertionEffect;\n// Use the earliest effect possible to reset the ref below.\nconst $458b0a5536c1a7cf$var$useEarlyEffect = typeof document !== 'undefined' ? ($458b0a5536c1a7cf$var$_React_useInsertionEffect = (0, $3whtM$react)['useInsertionEffect']) !== null && $458b0a5536c1a7cf$var$_React_useInsertionEffect !== void 0 ? $458b0a5536c1a7cf$var$_React_useInsertionEffect : (0, $3whtM$react).useLayoutEffect : ()=>{};\nfunction $458b0a5536c1a7cf$export$40bfa8c7b0832715(value, defaultValue, onChange) {\n // Store the value in both state and a ref. The state value will only be used when uncontrolled.\n // The ref is used to track the most current value, which is passed to the function setState callback.\n let [stateValue, setStateValue] = (0, $3whtM$useState)(value || defaultValue);\n let valueRef = (0, $3whtM$useRef)(stateValue);\n let isControlledRef = (0, $3whtM$useRef)(value !== undefined);\n let isControlled = value !== undefined;\n (0, $3whtM$useEffect)(()=>{\n let wasControlled = isControlledRef.current;\n if (wasControlled !== isControlled && process.env.NODE_ENV !== 'production') console.warn(`WARN: A component changed from ${wasControlled ? 'controlled' : 'uncontrolled'} to ${isControlled ? 'controlled' : 'uncontrolled'}.`);\n isControlledRef.current = isControlled;\n }, [\n isControlled\n ]);\n // After each render, update the ref to the current value.\n // This ensures that the setState callback argument is reset.\n // Note: the effect should not have any dependencies so that controlled values always reset.\n let currentValue = isControlled ? value : stateValue;\n $458b0a5536c1a7cf$var$useEarlyEffect(()=>{\n valueRef.current = currentValue;\n });\n let [, forceUpdate] = (0, $3whtM$useReducer)(()=>({}), {});\n let setValue = (0, $3whtM$useCallback)((value, ...args)=>{\n // @ts-ignore - TS doesn't know that T cannot be a function.\n let newValue = typeof value === 'function' ? value(valueRef.current) : value;\n if (!Object.is(valueRef.current, newValue)) {\n // Update the ref so that the next setState callback has the most recent value.\n valueRef.current = newValue;\n setStateValue(newValue);\n // Always trigger a re-render, even when controlled, so that the layout effect above runs to reset the value.\n forceUpdate();\n // Trigger onChange. Note that if setState is called multiple times in a single event,\n // onChange will be called for each one instead of only once.\n onChange === null || onChange === void 0 ? void 0 : onChange(newValue, ...args);\n }\n }, [\n onChange\n ]);\n return [\n currentValue,\n setValue\n ];\n}\n\n\nexport {$458b0a5536c1a7cf$export$40bfa8c7b0832715 as useControlledState};\n//# sourceMappingURL=useControlledState.module.js.map\n","import {useCallback as $hnMvi$useCallback} from \"react\";\nimport {useControlledState as $hnMvi$useControlledState} from \"@react-stately/utils\";\n\n/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */ \n\nfunction $fc909762b330b746$export$61c6a8c84e605fb6(props) {\n let [isOpen, setOpen] = (0, $hnMvi$useControlledState)(props.isOpen, props.defaultOpen || false, props.onOpenChange);\n const open = (0, $hnMvi$useCallback)(()=>{\n setOpen(true);\n }, [\n setOpen\n ]);\n const close = (0, $hnMvi$useCallback)(()=>{\n setOpen(false);\n }, [\n setOpen\n ]);\n const toggle = (0, $hnMvi$useCallback)(()=>{\n setOpen(!isOpen);\n }, [\n setOpen,\n isOpen\n ]);\n return {\n isOpen: isOpen,\n setOpen: setOpen,\n open: open,\n close: close,\n toggle: toggle\n };\n}\n\n\nexport {$fc909762b330b746$export$61c6a8c84e605fb6 as useOverlayTriggerState};\n//# sourceMappingURL=useOverlayTriggerState.module.js.map\n","import { OverlayProvider } from '@react-aria/overlays';\nimport { useOverlayTriggerState } from '@react-stately/overlays';\n\nimport type { Meta, StoryFn } from '@storybook/react';\nimport type { PageOverlayProps } from './PageOverlay';\n\nimport { PageOverlay } from './PageOverlay';\n\nimport { Button } from 'components/Buttons';\nimport { ButtonGroup } from 'components/ButtonGroup';\nimport { InputField } from 'components/InputField';\nimport { GridRow } from 'components/GridRow';\nimport { Repeater } from 'components/Repeater';\n\nconst codeString = `\n <PageOverlay isOpen={isOpen} title={title} onClose={onCloseFunction}\n onSubmit={onSubmitFunction} buttons={buttons}> {children} </PageOverlay>\n`;\n\n// eslint-disable-next-line import/no-default-export\nexport default {\n title: 'Molecules/PageOverlay',\n component: PageOverlay,\n argTypes: {\n isOpen: {\n table: {\n disable: true,\n },\n },\n noValidate: {\n control: 'boolean',\n },\n onSubmit: {\n table: {\n disable: true,\n },\n },\n onClose: {\n table: {\n disable: true,\n },\n },\n buttons: {\n table: {\n disable: true,\n },\n },\n },\n parameters: {\n inspectComponent: PageOverlay,\n codeString: codeString,\n },\n} as Meta<PageOverlayProps>;\n\nconst Template: StoryFn<PageOverlayProps> = (args: PageOverlayProps) => {\n const { open, close, isOpen } = useOverlayTriggerState({});\n return (\n <OverlayProvider>\n <Button variant=\"primary\" onClick={() => open()}>\n Open PageOverlay\n </Button>\n <PageOverlay\n {...args}\n isOpen={isOpen}\n buttons={\n <ButtonGroup reversed>\n <Button variant=\"primary\" onClick={() => close()}>\n OK\n </Button>\n <Button variant=\"secondary\" onClick={() => close()}>\n Cancel\n </Button>\n </ButtonGroup>\n }\n onClose={() => close()}\n >\n Your content goes here\n </PageOverlay>\n </OverlayProvider>\n );\n};\n\nconst defaultArgs: Partial<PageOverlayProps> = {\n title: 'Example Title',\n closeButtonAriaValueText: 'Close',\n noValidate: false,\n};\n\nexport const PageOverlayExample = Template.bind({});\nPageOverlayExample.args = {\n ...defaultArgs,\n};\n\nexport const Loading = Template.bind({});\nLoading.args = {\n ...defaultArgs,\n isLoading: true,\n spinnerAriaValueText: 'Loading',\n};\n\nconst LongContentTemplate: StoryFn<PageOverlayProps> = (args: PageOverlayProps) => {\n const { open, close, isOpen } = useOverlayTriggerState({});\n return (\n <OverlayProvider>\n <Button variant=\"primary\" onClick={() => open()}>\n Open PageOverlay\n </Button>\n <PageOverlay\n {...args}\n isOpen={isOpen}\n buttons={\n <GridRow>\n <GridRow.Column size=\"8\" mediumSize=\"9\" startPositon=\"2\" mediumStartPosition=\"3\">\n <ButtonGroup reversed>\n <Button variant=\"primary\" onClick={() => close()}>\n OK\n </Button>\n <Button variant=\"secondary\" onClick={() => close()}>\n Cancel\n </Button>\n </ButtonGroup>\n </GridRow.Column>\n </GridRow>\n }\n onClose={() => close()}\n >\n <GridRow marginTop=\"100\">\n <GridRow.Column size=\"8\" mediumSize=\"9\" startPositon=\"2\" mediumStartPosition=\"3\">\n <Repeater gap=\"100\">\n <div>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut ac dui et nibh eleifend ultricies a id\n nulla. Pellentesque eleifend sem a tellus dictum tempus. Proin non leo id risus placerat vulputate at ac\n erat. Ut fringilla imperdiet sollicitudin. Vestibulum ante ipsum primis in faucibus orci luctus et\n ultrices posuere cubilia curae; Gijs molestie ante ac magna ornare rhoncus non at quam. Mauris elementum\n luctus euismod. Pellentesque molestie malesuada purus, sed egestas lacus interdum sit amet. Morbi\n blandit lacus sit amet dictum pulvinar. Ut semper nunc ac enim imperdiet, non interdum diam gravida. In\n nunc tortor, mollis ac molestie dignissim, elementum sed quam. Suspendisse mollis venenatis Laura,\n pellentesque vestibulum elit consequat et. Aliquam fringilla tellus id libero tempus, sit amet suscipit\n augue tristique. Quisque cursus neque vel justo tristique, eget semper turpis elementum. Etiam venenatis\n mattis sapien ac mattis. Mauris vitae ultrices erat.\n </div>\n <div>\n Aliquam facilisis massa sed justo rhoncus bibendum. Sed lobortis urna orci, vitae porta leo placerat\n nec. Nam porta porttitor ornare. Suspendisse vehicula nunc nec egestas finibus. Aliquam non luctus\n risus. Pien ac diam tincidunt, bibendum sem eget, sollicitudin neque. Curabitur mauris risus, feugiat ac\n euismod non, vulputate ac justo. Curabitur pretium vehicula augue, blandit porta odio rutrum sit amet.\n Proin semper enim ut sapien tempor, a ornare ipsum faucibus.\n </div>\n <Button variant=\"primary\">Test Button</Button>\n <div>\n Cras bibendum arcu vitae nulla venenatis, at cursus urna dapibus. In hac habitasse platea dictumst. In\n porttitor at lectus nec rhoncus. In hac habitasse platea dictumst. Sed nec lectus neque. Aliquam erat\n volutpat. Morbi elit orci, ultricies a porttitor eget, eleifend eu metus. Maarten sollicitudin vitae\n massa a tempor. Aliquam dignissim metus id sem sollicitudin, eget lacinia nulla imperdiet. Nullam nec\n vestibulum eros, ut aliquam libero. Nulla hendrerit cursus ante id auctor. Curabitur condimentum\n malesuada maximus. Aliquam felis diam, gravida nec eleifend quis, placerat et orci.\n </div>\n <div>\n Nulla leo ligula, hendrerit vel egestas in, suscipit vitae erat. Vivamus interdum quam lacinia, egestas\n felis non, volutpat velit. Vestibulum orci diam, tincidunt ac mattis quis, ornare posuere magna. Aliquam\n erat volutpat. Maecenas facilisis lacus id ante efficitur, non dignissim lorem suscipit. Praesent at\n posuere velit. Nulla imperdiet, dui rhoncus volutpat feugiat, eros mauris cursus justo, a tincidunt\n ipsum ipsum eu nisl. Nulla eu dui Thierry. Aliquam vitae risus ut velit fringilla sodales nec id lacus.\n Interdum et malesuada fames ac ante ipsum primis in faucibus. Suspendisse ullamcorper purus quis nunc\n placerat, vel bibendum urna mollis. Nulla facilisi. Phasellus sed erat nec ex ullamcorper viverra.\n Phasellus convallis nibh sed dolor vulputate convallis. Phasellus ac posuere sapien, et elementum ipsum.\n </div>\n <InputField id=\"test-input\" placeholder=\"Test Input\" />\n <div>\n Sed malesuada ut nulla ut maximus. Class aptent taciti sociosqu ad litora torquent per conubia nostra,\n per inceptos himenaeos. Morten in libero rhoncus, maximus tortor sit amet, molestie ex. Mauris rhoncus\n et erat dapibus aliquam. Vestibulum placerat quam eget lorem tempor, vel venenatis lorem malesuada. Duis\n ut venenatis arcu. Cras lacinia mi ac dui sollicitudin semper sit amet eget nisl. Fusce viverra ex eget\n tortor molestie dictum. Cras ullamcorper faucibus nisi in congue. Sanne in tristique est. Praesent id\n rhoncus ligula, ut porta dui. Sed tincidunt, mi nec varius auctor, nunc diam venenatis felis, at\n facilisis tortor sem et magna. Aliquam erat volutpat.\n </div>\n <div>\n Proin ipsum ante, auctor id consectetur a, pulvinar id nibh. Phasellus molestie quam eu mi lacinia\n condimentum. Nullam fermentum id diam eu pharetra. Donec dictum sem vitae Jos scelerisque semper.\n Suspendisse sed facilisis orci. Sed ut scelerisque odio. Curabitur felis felis, finibus ac orci at,\n pellentesque efficitur risus. Sed et leo ac orci mollis tincidunt et pulvinar velit. Duis non nibh\n tincidunt, lacinia urna a, fringilla augue. Benjamin fermentum, massa a mollis cursus, ex dui tincidunt\n tellus, ut sollicitudin ex neque ac sapien.\n </div>\n <div>\n Nunc rhoncus imperdiet leo. Fusce interdum malesuada aliquet. Aenean porttitor, tortor et volutpat\n blandit, sapien diam scelerisque massa, ac facilisis metus turpis id quam. Donec ac elementum augue,\n congue pulvinar arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. Cras tempor\n convallis elit, id vehicula Robin semper nec. Sed ut ultrices nulla. Cras nec dolor justo. Proin mollis\n mauris ligula, luctus faucibus dolor ultrices ac. Nunc quis mauris fringilla, pellentesque massa nec,\n dictum metus. Praesent odio ligula, tincidunt ultrices maximus quis, accumsan ut odio. Nullam iaculis\n molestie nulla quis ultrices. Praesent quam velit, sagittis eget auctor a, dignissim ut massa. Donec\n mollis at lorem sit amet accumsan. Praesent nec nulla laoreet nunc pretium egestas. Malesuada Wim arcu\n pharetra, dictum nibh a, facilisis risus.\n </div>\n </Repeater>\n </GridRow.Column>\n </GridRow>\n </PageOverlay>\n </OverlayProvider>\n );\n};\n\nexport const WithLongComplexContent = LongContentTemplate.bind({});\nWithLongComplexContent.args = {\n ...defaultArgs,\n};\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PageOverlay.stories.js","names":["$1CcWn$react","$1CcWn$useState","$1CcWn$useRef","$1CcWn$useEffect","$1CcWn$useReducer","$1CcWn$useCallback","$kE40A$useCallback"],"sources":["../../../node_modules/react-stately/dist/private/utils/useControlledState.mjs","../../../node_modules/react-stately/dist/private/overlays/useOverlayTriggerState.mjs","../../../src/components/PageOverlay/PageOverlay.stories.tsx"],"sourcesContent":["import $1CcWn$react, {useState as $1CcWn$useState, useRef as $1CcWn$useRef, useEffect as $1CcWn$useEffect, useReducer as $1CcWn$useReducer, useCallback as $1CcWn$useCallback} from \"react\";\n\n/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */ \n// Use the earliest effect possible to reset the ref below.\nconst $3e6197669829fe11$var$useEarlyEffect = typeof document !== 'undefined' ? (0, $1CcWn$react)['useInsertionEffect'] ?? (0, $1CcWn$react).useLayoutEffect : ()=>{};\nfunction $3e6197669829fe11$export$40bfa8c7b0832715(value, defaultValue, onChange) {\n // Store the value in both state and a ref. The state value will only be used when uncontrolled.\n // The ref is used to track the most current value, which is passed to the function setState callback.\n let [stateValue, setStateValue] = (0, $1CcWn$useState)(value || defaultValue);\n let valueRef = (0, $1CcWn$useRef)(stateValue);\n let isControlledRef = (0, $1CcWn$useRef)(value !== undefined);\n let isControlled = value !== undefined;\n (0, $1CcWn$useEffect)(()=>{\n let wasControlled = isControlledRef.current;\n if (wasControlled !== isControlled && process.env.NODE_ENV !== 'production') console.warn(`WARN: A component changed from ${wasControlled ? 'controlled' : 'uncontrolled'} to ${isControlled ? 'controlled' : 'uncontrolled'}.`);\n isControlledRef.current = isControlled;\n }, [\n isControlled\n ]);\n // After each render, update the ref to the current value.\n // This ensures that the setState callback argument is reset.\n // Note: the effect should not have any dependencies so that controlled values always reset.\n let currentValue = isControlled ? value : stateValue;\n $3e6197669829fe11$var$useEarlyEffect(()=>{\n valueRef.current = currentValue;\n });\n let [, forceUpdate] = (0, $1CcWn$useReducer)(()=>({}), {});\n let setValue = (0, $1CcWn$useCallback)((value, ...args)=>{\n // @ts-ignore - TS doesn't know that T cannot be a function.\n let newValue = typeof value === 'function' ? value(valueRef.current) : value;\n if (!Object.is(valueRef.current, newValue)) {\n // Update the ref so that the next setState callback has the most recent value.\n valueRef.current = newValue;\n setStateValue(newValue);\n // Always trigger a re-render, even when controlled, so that the layout effect above runs to reset the value.\n forceUpdate();\n // Trigger onChange. Note that if setState is called multiple times in a single event,\n // onChange will be called for each one instead of only once.\n onChange?.(newValue, ...args);\n }\n }, [\n onChange\n ]);\n return [\n currentValue,\n setValue\n ];\n}\n\n\nexport {$3e6197669829fe11$export$40bfa8c7b0832715 as useControlledState};\n//# sourceMappingURL=useControlledState.mjs.map\n","import {useControlledState as $3e6197669829fe11$export$40bfa8c7b0832715} from \"../utils/useControlledState.mjs\";\nimport {useCallback as $kE40A$useCallback} from \"react\";\n\n/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */ \n\nfunction $f11fb0bcf1b2687a$export$61c6a8c84e605fb6(props) {\n let [isOpen, setOpen] = (0, $3e6197669829fe11$export$40bfa8c7b0832715)(props.isOpen, props.defaultOpen || false, props.onOpenChange);\n const open = (0, $kE40A$useCallback)(()=>{\n setOpen(true);\n }, [\n setOpen\n ]);\n const close = (0, $kE40A$useCallback)(()=>{\n setOpen(false);\n }, [\n setOpen\n ]);\n const toggle = (0, $kE40A$useCallback)(()=>{\n setOpen(!isOpen);\n }, [\n setOpen,\n isOpen\n ]);\n return {\n isOpen: isOpen,\n setOpen: setOpen,\n open: open,\n close: close,\n toggle: toggle\n };\n}\n\n\nexport {$f11fb0bcf1b2687a$export$61c6a8c84e605fb6 as useOverlayTriggerState};\n//# sourceMappingURL=useOverlayTriggerState.mjs.map\n","import { OverlayProvider } from '@react-aria/overlays';\nimport { useOverlayTriggerState } from '@react-stately/overlays';\n\nimport type { Meta, StoryFn } from '@storybook/react';\nimport type { PageOverlayProps } from './PageOverlay';\n\nimport { PageOverlay } from './PageOverlay';\n\nimport { Button } from 'components/Buttons';\nimport { ButtonGroup } from 'components/ButtonGroup';\nimport { InputField } from 'components/InputField';\nimport { GridRow } from 'components/GridRow';\nimport { Repeater } from 'components/Repeater';\n\nconst codeString = `\n <PageOverlay isOpen={isOpen} title={title} onClose={onCloseFunction}\n onSubmit={onSubmitFunction} buttons={buttons}> {children} </PageOverlay>\n`;\n\n// eslint-disable-next-line import/no-default-export\nexport default {\n title: 'Molecules/PageOverlay',\n component: PageOverlay,\n argTypes: {\n isOpen: {\n table: {\n disable: true,\n },\n },\n noValidate: {\n control: 'boolean',\n },\n onSubmit: {\n table: {\n disable: true,\n },\n },\n onClose: {\n table: {\n disable: true,\n },\n },\n buttons: {\n table: {\n disable: true,\n },\n },\n },\n parameters: {\n inspectComponent: PageOverlay,\n codeString: codeString,\n },\n} as Meta<PageOverlayProps>;\n\nconst Template: StoryFn<PageOverlayProps> = (args: PageOverlayProps) => {\n const { open, close, isOpen } = useOverlayTriggerState({});\n return (\n <OverlayProvider>\n <Button variant=\"primary\" onClick={() => open()}>\n Open PageOverlay\n </Button>\n <PageOverlay\n {...args}\n isOpen={isOpen}\n buttons={\n <ButtonGroup reversed>\n <Button variant=\"primary\" onClick={() => close()}>\n OK\n </Button>\n <Button variant=\"secondary\" onClick={() => close()}>\n Cancel\n </Button>\n </ButtonGroup>\n }\n onClose={() => close()}\n >\n Your content goes here\n </PageOverlay>\n </OverlayProvider>\n );\n};\n\nconst defaultArgs: Partial<PageOverlayProps> = {\n title: 'Example Title',\n closeButtonAriaValueText: 'Close',\n noValidate: false,\n};\n\nexport const PageOverlayExample = Template.bind({});\nPageOverlayExample.args = {\n ...defaultArgs,\n};\n\nexport const Loading = Template.bind({});\nLoading.args = {\n ...defaultArgs,\n isLoading: true,\n spinnerAriaValueText: 'Loading',\n};\n\nconst LongContentTemplate: StoryFn<PageOverlayProps> = (args: PageOverlayProps) => {\n const { open, close, isOpen } = useOverlayTriggerState({});\n return (\n <OverlayProvider>\n <Button variant=\"primary\" onClick={() => open()}>\n Open PageOverlay\n </Button>\n <PageOverlay\n {...args}\n isOpen={isOpen}\n buttons={\n <GridRow>\n <GridRow.Column size=\"8\" mediumSize=\"9\" startPositon=\"2\" mediumStartPosition=\"3\">\n <ButtonGroup reversed>\n <Button variant=\"primary\" onClick={() => close()}>\n OK\n </Button>\n <Button variant=\"secondary\" onClick={() => close()}>\n Cancel\n </Button>\n </ButtonGroup>\n </GridRow.Column>\n </GridRow>\n }\n onClose={() => close()}\n >\n <GridRow marginTop=\"100\">\n <GridRow.Column size=\"8\" mediumSize=\"9\" startPositon=\"2\" mediumStartPosition=\"3\">\n <Repeater gap=\"100\">\n <div>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut ac dui et nibh eleifend ultricies a id\n nulla. Pellentesque eleifend sem a tellus dictum tempus. Proin non leo id risus placerat vulputate at ac\n erat. Ut fringilla imperdiet sollicitudin. Vestibulum ante ipsum primis in faucibus orci luctus et\n ultrices posuere cubilia curae; Gijs molestie ante ac magna ornare rhoncus non at quam. Mauris elementum\n luctus euismod. Pellentesque molestie malesuada purus, sed egestas lacus interdum sit amet. Morbi\n blandit lacus sit amet dictum pulvinar. Ut semper nunc ac enim imperdiet, non interdum diam gravida. In\n nunc tortor, mollis ac molestie dignissim, elementum sed quam. Suspendisse mollis venenatis Laura,\n pellentesque vestibulum elit consequat et. Aliquam fringilla tellus id libero tempus, sit amet suscipit\n augue tristique. Quisque cursus neque vel justo tristique, eget semper turpis elementum. Etiam venenatis\n mattis sapien ac mattis. Mauris vitae ultrices erat.\n </div>\n <div>\n Aliquam facilisis massa sed justo rhoncus bibendum. Sed lobortis urna orci, vitae porta leo placerat\n nec. Nam porta porttitor ornare. Suspendisse vehicula nunc nec egestas finibus. Aliquam non luctus\n risus. Pien ac diam tincidunt, bibendum sem eget, sollicitudin neque. Curabitur mauris risus, feugiat ac\n euismod non, vulputate ac justo. Curabitur pretium vehicula augue, blandit porta odio rutrum sit amet.\n Proin semper enim ut sapien tempor, a ornare ipsum faucibus.\n </div>\n <Button variant=\"primary\">Test Button</Button>\n <div>\n Cras bibendum arcu vitae nulla venenatis, at cursus urna dapibus. In hac habitasse platea dictumst. In\n porttitor at lectus nec rhoncus. In hac habitasse platea dictumst. Sed nec lectus neque. Aliquam erat\n volutpat. Morbi elit orci, ultricies a porttitor eget, eleifend eu metus. Maarten sollicitudin vitae\n massa a tempor. Aliquam dignissim metus id sem sollicitudin, eget lacinia nulla imperdiet. Nullam nec\n vestibulum eros, ut aliquam libero. Nulla hendrerit cursus ante id auctor. Curabitur condimentum\n malesuada maximus. Aliquam felis diam, gravida nec eleifend quis, placerat et orci.\n </div>\n <div>\n Nulla leo ligula, hendrerit vel egestas in, suscipit vitae erat. Vivamus interdum quam lacinia, egestas\n felis non, volutpat velit. Vestibulum orci diam, tincidunt ac mattis quis, ornare posuere magna. Aliquam\n erat volutpat. Maecenas facilisis lacus id ante efficitur, non dignissim lorem suscipit. Praesent at\n posuere velit. Nulla imperdiet, dui rhoncus volutpat feugiat, eros mauris cursus justo, a tincidunt\n ipsum ipsum eu nisl. Nulla eu dui Thierry. Aliquam vitae risus ut velit fringilla sodales nec id lacus.\n Interdum et malesuada fames ac ante ipsum primis in faucibus. Suspendisse ullamcorper purus quis nunc\n placerat, vel bibendum urna mollis. Nulla facilisi. Phasellus sed erat nec ex ullamcorper viverra.\n Phasellus convallis nibh sed dolor vulputate convallis. Phasellus ac posuere sapien, et elementum ipsum.\n </div>\n <InputField id=\"test-input\" placeholder=\"Test Input\" />\n <div>\n Sed malesuada ut nulla ut maximus. Class aptent taciti sociosqu ad litora torquent per conubia nostra,\n per inceptos himenaeos. Morten in libero rhoncus, maximus tortor sit amet, molestie ex. Mauris rhoncus\n et erat dapibus aliquam. Vestibulum placerat quam eget lorem tempor, vel venenatis lorem malesuada. Duis\n ut venenatis arcu. Cras lacinia mi ac dui sollicitudin semper sit amet eget nisl. Fusce viverra ex eget\n tortor molestie dictum. Cras ullamcorper faucibus nisi in congue. Sanne in tristique est. Praesent id\n rhoncus ligula, ut porta dui. Sed tincidunt, mi nec varius auctor, nunc diam venenatis felis, at\n facilisis tortor sem et magna. Aliquam erat volutpat.\n </div>\n <div>\n Proin ipsum ante, auctor id consectetur a, pulvinar id nibh. Phasellus molestie quam eu mi lacinia\n condimentum. Nullam fermentum id diam eu pharetra. Donec dictum sem vitae Jos scelerisque semper.\n Suspendisse sed facilisis orci. Sed ut scelerisque odio. Curabitur felis felis, finibus ac orci at,\n pellentesque efficitur risus. Sed et leo ac orci mollis tincidunt et pulvinar velit. Duis non nibh\n tincidunt, lacinia urna a, fringilla augue. Benjamin fermentum, massa a mollis cursus, ex dui tincidunt\n tellus, ut sollicitudin ex neque ac sapien.\n </div>\n <div>\n Nunc rhoncus imperdiet leo. Fusce interdum malesuada aliquet. Aenean porttitor, tortor et volutpat\n blandit, sapien diam scelerisque massa, ac facilisis metus turpis id quam. Donec ac elementum augue,\n congue pulvinar arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. Cras tempor\n convallis elit, id vehicula Robin semper nec. Sed ut ultrices nulla. Cras nec dolor justo. Proin mollis\n mauris ligula, luctus faucibus dolor ultrices ac. Nunc quis mauris fringilla, pellentesque massa nec,\n dictum metus. Praesent odio ligula, tincidunt ultrices maximus quis, accumsan ut odio. Nullam iaculis\n molestie nulla quis ultrices. Praesent quam velit, sagittis eget auctor a, dignissim ut massa. Donec\n mollis at lorem sit amet accumsan. Praesent nec nulla laoreet nunc pretium egestas. Malesuada Wim arcu\n pharetra, dictum nibh a, facilisis risus.\n </div>\n </Repeater>\n </GridRow.Column>\n </GridRow>\n </PageOverlay>\n </OverlayProvider>\n );\n};\n\nexport const WithLongComplexContent = LongContentTemplate.bind({});\nWithLongComplexContent.args = {\n ...defaultArgs,\n};\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../../dist-V_v3kC0L.js";
|
|
2
2
|
import { t as e } from "../../RadioGroup-JeTjVp5B.js";
|
|
3
|
-
import { i as t, n, t as r } from "../../react.esm-
|
|
3
|
+
import { i as t, n, t as r } from "../../react.esm-CweFe1CK.js";
|
|
4
4
|
import { jsx as i } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/RadioGroup/Radiogroup.test.tsx
|
|
6
6
|
var a = [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Radiogroup.test.js","names":[],"sources":["../../../src/components/RadioGroup/Radiogroup.test.tsx"],"sourcesContent":["import '@testing-library/jest-dom';\nimport { render, screen, fireEvent } from '@testing-library/react';\n\nimport { RadioGroup } from './RadioGroup';\n\nconst options = [\n { id: '1', titleLabel: 'Option 1', value: 'option1' },\n { id: '2', titleLabel: 'Option 2', value: 'option2' },\n];\n\ndescribe('RadioGroup', () => {\n it('should render correctly', () => {\n render(<RadioGroup label=\"Test Label\" options={options} onChange={jest.fn()} />);\n expect(screen.getByText('Test Label')).toBeInTheDocument();\n expect(screen.getByText('Option 1')).toBeInTheDocument();\n expect(screen.getByText('Option 2')).toBeInTheDocument();\n });\n\n it('should call onChange when an option is selected', () => {\n const handleChange = jest.fn();\n render(<RadioGroup label=\"Test Label\" options={options} onChange={handleChange} />);\n\n const option1 = screen.getByLabelText('Option 1');\n fireEvent.click(option1);\n expect(handleChange).toHaveBeenCalledWith('option1');\n });\n\n it('should not allow selection when disabled', () => {\n const handleChange = jest.fn();\n render(<RadioGroup label=\"Test Label\" options={options} onChange={handleChange} disabled />);\n\n const option1 = screen.getByLabelText('Option 1');\n fireEvent.click(option1);\n expect(handleChange).not.toHaveBeenCalled();\n });\n});\n"],"mappings":";;;;;AAKA,IAAM,IAAU,CACd;CAAE,IAAI;CAAK,YAAY;CAAY,OAAO;CAAW,EACrD;CAAE,IAAI;CAAK,YAAY;CAAY,OAAO;CAAW,CACtD;AAED,SAAS,oBAAoB;
|
|
1
|
+
{"version":3,"file":"Radiogroup.test.js","names":[],"sources":["../../../src/components/RadioGroup/Radiogroup.test.tsx"],"sourcesContent":["import '@testing-library/jest-dom';\nimport { render, screen, fireEvent } from '@testing-library/react';\n\nimport { RadioGroup } from './RadioGroup';\n\nconst options = [\n { id: '1', titleLabel: 'Option 1', value: 'option1' },\n { id: '2', titleLabel: 'Option 2', value: 'option2' },\n];\n\ndescribe('RadioGroup', () => {\n it('should render correctly', () => {\n render(<RadioGroup label=\"Test Label\" options={options} onChange={jest.fn()} />);\n expect(screen.getByText('Test Label')).toBeInTheDocument();\n expect(screen.getByText('Option 1')).toBeInTheDocument();\n expect(screen.getByText('Option 2')).toBeInTheDocument();\n });\n\n it('should call onChange when an option is selected', () => {\n const handleChange = jest.fn();\n render(<RadioGroup label=\"Test Label\" options={options} onChange={handleChange} />);\n\n const option1 = screen.getByLabelText('Option 1');\n fireEvent.click(option1);\n expect(handleChange).toHaveBeenCalledWith('option1');\n });\n\n it('should not allow selection when disabled', () => {\n const handleChange = jest.fn();\n render(<RadioGroup label=\"Test Label\" options={options} onChange={handleChange} disabled />);\n\n const option1 = screen.getByLabelText('Option 1');\n fireEvent.click(option1);\n expect(handleChange).not.toHaveBeenCalled();\n });\n});\n"],"mappings":";;;;;AAKA,IAAM,IAAU,CACd;CAAE,IAAI;CAAK,YAAY;CAAY,OAAO;CAAW,EACrD;CAAE,IAAI;CAAK,YAAY;CAAY,OAAO;CAAW,CACtD;AAED,SAAS,oBAAoB;CAiB3B,AAhBA,GAAG,iCAAiC;EAIlC,AAHA,EAAO,kBAAC,GAAD;GAAY,OAAM;GAAsB;GAAS,UAAU,KAAK,IAAI;GAAI,CAAA,CAAC,EAChF,OAAO,EAAO,UAAU,aAAa,CAAC,CAAC,mBAAmB,EAC1D,OAAO,EAAO,UAAU,WAAW,CAAC,CAAC,mBAAmB,EACxD,OAAO,EAAO,UAAU,WAAW,CAAC,CAAC,mBAAmB;GACxD,EAEF,GAAG,yDAAyD;EAC1D,IAAM,IAAe,KAAK,IAAI;EAC9B,EAAO,kBAAC,GAAD;GAAY,OAAM;GAAsB;GAAS,UAAU;GAAgB,CAAA,CAAC;EAEnF,IAAM,IAAU,EAAO,eAAe,WAAW;EAEjD,AADA,EAAU,MAAM,EAAQ,EACxB,OAAO,EAAa,CAAC,qBAAqB,UAAU;GACpD,EAEF,GAAG,kDAAkD;EACnD,IAAM,IAAe,KAAK,IAAI;EAC9B,EAAO,kBAAC,GAAD;GAAY,OAAM;GAAsB;GAAS,UAAU;GAAc,UAAA;GAAW,CAAA,CAAC;EAE5F,IAAM,IAAU,EAAO,eAAe,WAAW;EAEjD,AADA,EAAU,MAAM,EAAQ,EACxB,OAAO,EAAa,CAAC,IAAI,kBAAkB;GAC3C;EACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlockFormatPlugin.js","names":[],"sources":["../../../../../src/components/RteEditor/Plugins/BlockFormatPlugin/BlockFormatPlugin.tsx"],"sourcesContent":["import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport { clsx } from 'clsx';\nimport { $getSelection, $isRangeSelection, FORMAT_TEXT_COMMAND } from 'lexical';\nimport { useEffect, useState } from 'react';\n\nimport type { JSX } from 'react';\n\nimport { Icon } from 'components/Icon';\nimport styles from 'components/RteEditor/RteEditor.module.css';\nimport { useTranslation } from 'components/RteEditor/hooks/useTranslation';\n\ntype BlockTypesType = 'bold' | 'italic';\nconst BLOCK_TYPE_ICONS = {\n bold: 'Bold',\n italic: 'Italic',\n};\n\nconst BlockTypes = ['bold', 'italic'];\n\nexport const BlockFormatPlugin = (): JSX.Element => {\n const t = useTranslation();\n const [editor] = useLexicalComposerContext();\n const [isBold, setIsBold] = useState(false);\n const [isItalic, setIsItalic] = useState(false);\n\n const onClick = (type: BlockTypesType): void => {\n editor.dispatchCommand(FORMAT_TEXT_COMMAND, type);\n };\n\n useEffect(() => {\n const removeStatusListener = editor.registerUpdateListener(({ editorState }) => {\n editorState.read(() => {\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n setIsBold(selection.hasFormat('bold'));\n setIsItalic(selection.hasFormat('italic'));\n }\n });\n });\n\n return () => {\n removeStatusListener();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editor]);\n\n return (\n <div className={styles['editor__toolbar-button-group']}>\n {BlockTypes.map((type) => (\n <button\n onClick={() => onClick(type as BlockTypesType)}\n key={type}\n title={type === 'bold' ? t.format.boldTooltip : t.format.italicTooltip}\n className={clsx(\n styles['editor__toolbar-button'],\n styles[`editor__toolbar-button--${type}`],\n type === 'bold' && isBold && styles['editor__toolbar-button--active'],\n type === 'italic' && isItalic && styles['editor__toolbar-button--active']\n )}\n aria-label={`${type === 'bold' ? t.aria.labels.bold : t.aria.labels.italic}`}\n aria-keyshortcuts={`${type === 'bold' ? t.aria.keyshortcuts.bold : t.aria.keyshortcuts.italic}`}\n type=\"button\"\n >\n <Icon name={BLOCK_TYPE_ICONS[type as keyof typeof Icon]} size={24} />\n </button>\n ))}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;AAYA,IAAM,IAAmB;CACvB,MAAM;CACN,QAAQ;CACT,EAEK,IAAa,CAAC,QAAQ,SAAS,EAExB,UAAuC;CAClD,IAAM,IAAI,GAAgB,EACpB,CAAC,KAAU,GAA2B,EACtC,CAAC,GAAQ,KAAa,EAAS,GAAM,EACrC,CAAC,GAAU,KAAe,EAAS,GAAM,EAEzC,KAAW,MAA+B;
|
|
1
|
+
{"version":3,"file":"BlockFormatPlugin.js","names":[],"sources":["../../../../../src/components/RteEditor/Plugins/BlockFormatPlugin/BlockFormatPlugin.tsx"],"sourcesContent":["import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport { clsx } from 'clsx';\nimport { $getSelection, $isRangeSelection, FORMAT_TEXT_COMMAND } from 'lexical';\nimport { useEffect, useState } from 'react';\n\nimport type { JSX } from 'react';\n\nimport { Icon } from 'components/Icon';\nimport styles from 'components/RteEditor/RteEditor.module.css';\nimport { useTranslation } from 'components/RteEditor/hooks/useTranslation';\n\ntype BlockTypesType = 'bold' | 'italic';\nconst BLOCK_TYPE_ICONS = {\n bold: 'Bold',\n italic: 'Italic',\n};\n\nconst BlockTypes = ['bold', 'italic'];\n\nexport const BlockFormatPlugin = (): JSX.Element => {\n const t = useTranslation();\n const [editor] = useLexicalComposerContext();\n const [isBold, setIsBold] = useState(false);\n const [isItalic, setIsItalic] = useState(false);\n\n const onClick = (type: BlockTypesType): void => {\n editor.dispatchCommand(FORMAT_TEXT_COMMAND, type);\n };\n\n useEffect(() => {\n const removeStatusListener = editor.registerUpdateListener(({ editorState }) => {\n editorState.read(() => {\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n setIsBold(selection.hasFormat('bold'));\n setIsItalic(selection.hasFormat('italic'));\n }\n });\n });\n\n return () => {\n removeStatusListener();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editor]);\n\n return (\n <div className={styles['editor__toolbar-button-group']}>\n {BlockTypes.map((type) => (\n <button\n onClick={() => onClick(type as BlockTypesType)}\n key={type}\n title={type === 'bold' ? t.format.boldTooltip : t.format.italicTooltip}\n className={clsx(\n styles['editor__toolbar-button'],\n styles[`editor__toolbar-button--${type}`],\n type === 'bold' && isBold && styles['editor__toolbar-button--active'],\n type === 'italic' && isItalic && styles['editor__toolbar-button--active']\n )}\n aria-label={`${type === 'bold' ? t.aria.labels.bold : t.aria.labels.italic}`}\n aria-keyshortcuts={`${type === 'bold' ? t.aria.keyshortcuts.bold : t.aria.keyshortcuts.italic}`}\n type=\"button\"\n >\n <Icon name={BLOCK_TYPE_ICONS[type as keyof typeof Icon]} size={24} />\n </button>\n ))}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;AAYA,IAAM,IAAmB;CACvB,MAAM;CACN,QAAQ;CACT,EAEK,IAAa,CAAC,QAAQ,SAAS,EAExB,UAAuC;CAClD,IAAM,IAAI,GAAgB,EACpB,CAAC,KAAU,GAA2B,EACtC,CAAC,GAAQ,KAAa,EAAS,GAAM,EACrC,CAAC,GAAU,KAAe,EAAS,GAAM,EAEzC,KAAW,MAA+B;EAC9C,EAAO,gBAAgB,GAAqB,EAAK;;CAoBnD,OAjBA,QAAgB;EACd,IAAM,IAAuB,EAAO,wBAAwB,EAAE,qBAAkB;GAC9E,EAAY,WAAW;IACrB,IAAM,IAAY,GAAe;IACjC,AAAI,EAAkB,EAAU,KAC9B,EAAU,EAAU,UAAU,OAAO,CAAC,EACtC,EAAY,EAAU,UAAU,SAAS,CAAC;KAE5C;IACF;EAEF,aAAa;GACX,GAAsB;;IAGvB,CAAC,EAAO,CAAC,EAGV,kBAAC,OAAD;EAAK,WAAW,EAAO;YACpB,EAAW,KAAK,MACf,kBAAC,UAAD;GACE,eAAe,EAAQ,EAAuB;GAE9C,OAAO,MAAS,SAAS,EAAE,OAAO,cAAc,EAAE,OAAO;GACzD,WAAW,EACT,EAAO,2BACP,EAAO,2BAA2B,MAClC,MAAS,UAAU,KAAU,EAAO,mCACpC,MAAS,YAAY,KAAY,EAAO,kCACzC;GACD,cAAY,GAAG,MAAS,SAAS,EAAE,KAAK,OAAO,OAAO,EAAE,KAAK,OAAO;GACpE,qBAAmB,GAAG,MAAS,SAAS,EAAE,KAAK,aAAa,OAAO,EAAE,KAAK,aAAa;GACvF,MAAK;aAEL,kBAAC,GAAD;IAAM,MAAM,EAAiB;IAA4B,MAAM;IAAM,CAAA;GAC9D,EAbF,EAaE,CACT;EACE,CAAA"}
|
package/dist/components/RteEditor/Plugins/CourseCataloguePlugin/CourseCataloguePlugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CourseCataloguePlugin.js","names":[],"sources":["../../../../../src/components/RteEditor/Plugins/CourseCataloguePlugin/CourseCataloguePlugin.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\r\nimport { clsx } from 'clsx';\r\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\r\nimport {\r\n $createRangeSelection,\r\n $createTextNode,\r\n $getSelection,\r\n $isRangeSelection,\r\n $isTextNode,\r\n $setSelection,\r\n COMMAND_PRIORITY_CRITICAL,\r\n COMMAND_PRIORITY_LOW,\r\n COPY_COMMAND,\r\n KEY_DOWN_COMMAND,\r\n mergeRegister,\r\n} from 'lexical';\r\nimport { $getNearestNodeOfType } from '@lexical/utils';\r\n\r\nimport type { RefObject } from 'react';\r\nimport type { LexicalNode, TextNode } from 'lexical';\r\nimport type { SearchResponse } from './AddCatalogueLinkForm';\r\n\r\nimport { AddCatalogueLinkForm } from './AddCatalogueLinkForm';\r\n\r\nimport styles from 'components/RteEditor/RteEditor.module.css';\r\nimport { useTranslation } from 'components/RteEditor/hooks/useTranslation';\r\nimport {\r\n $getLinkTypeFromNode,\r\n CourseCatalogueNode,\r\n INSERT_COURSE_CATALOGUE_LINK,\r\n REMOVE_COURSE_CATALOGUE_LINK,\r\n} from 'components/RteEditor/nodes/CourseCatalogueNode';\r\nimport { useOnClickOutside } from 'components/hooks/useOnClickOutside';\r\n\r\ninterface CourseCataloguePluginProps {\r\n onSearch: (query: string, linkType: 'course' | 'programme') => void;\r\n searchResponse: SearchResponse;\r\n parentScrollPosition: number;\r\n}\r\n\r\nexport const CourseCataloguePlugin = ({\r\n onSearch,\r\n searchResponse,\r\n parentScrollPosition,\r\n}: CourseCataloguePluginProps) => {\r\n const [editor] = useLexicalComposerContext();\r\n const t = useTranslation();\r\n const [courseIsActive, setCourseIsActive] = useState(false);\r\n const [programmeIsActive, setProgrammeIsActive] = useState(false);\r\n const courseButtonRef = useRef<HTMLButtonElement>(null);\r\n const programmeButtonRef = useRef<HTMLButtonElement>(null);\r\n const flyoutRef = useRef<HTMLDivElement>(null);\r\n const [flyoutPosition, setFlyoutPosition] = useState<{ top: number; left: number } | null>(null);\r\n const [type, setType] = useState<'course' | 'programme'>('course');\r\n const isVisibleRef = useRef(flyoutPosition !== null);\r\n\r\n const openFlyout = (type: 'course' | 'programme') => {\r\n setType(type);\r\n const rect =\r\n type === 'course'\r\n ? courseButtonRef.current?.getBoundingClientRect()\r\n : programmeButtonRef.current?.getBoundingClientRect();\r\n if (rect) {\r\n setFlyoutPosition({ top: rect.bottom, left: rect.left });\r\n }\r\n };\r\n\r\n const closeFlyout = () => {\r\n onSearch('', type);\r\n setFlyoutPosition(null);\r\n };\r\n\r\n useEffect(() => {\r\n const removeKeyboardShortcut = editor.registerCommand(\r\n KEY_DOWN_COMMAND,\r\n (event: KeyboardEvent) => {\r\n if (event.ctrlKey && event.shiftKey && event.altKey && event.key === 'C') {\r\n event.preventDefault();\r\n openFlyout('course');\r\n return true;\r\n }\r\n if (event.ctrlKey && event.shiftKey && event.altKey && event.key === 'P') {\r\n event.preventDefault();\r\n openFlyout('programme');\r\n return true;\r\n }\r\n return false;\r\n },\r\n COMMAND_PRIORITY_CRITICAL\r\n );\r\n\r\n const removeStatusListener = editor.registerUpdateListener(({ editorState }) => {\r\n editorState.read(() => {\r\n const selection = $getSelection();\r\n if ($isRangeSelection(selection)) {\r\n const anchorNode = selection.anchor.getNode();\r\n const offset = selection.anchor.offset;\r\n\r\n if (\r\n $isTextNode(anchorNode) &&\r\n offset === anchorNode.getTextContentSize() &&\r\n anchorNode.getNextSibling() instanceof CourseCatalogueNode\r\n ) {\r\n // Cursor staat aan het begin van de link!\r\n const courseCatalogueLink = anchorNode.getNextSibling();\r\n if (courseCatalogueLink) {\r\n const linkType = $getLinkTypeFromNode(courseCatalogueLink);\r\n setCourseIsActive(linkType === 'course');\r\n setProgrammeIsActive(linkType === 'programme');\r\n return;\r\n }\r\n }\r\n\r\n const courseCatalogueLink = $getNearestNodeOfType(anchorNode, CourseCatalogueNode);\r\n if (courseCatalogueLink) {\r\n const linkType = $getLinkTypeFromNode(courseCatalogueLink);\r\n setCourseIsActive(linkType === 'course');\r\n setProgrammeIsActive(linkType === 'programme');\r\n return;\r\n }\r\n setCourseIsActive(false);\r\n setProgrammeIsActive(false);\r\n }\r\n });\r\n });\r\n\r\n const moveToEndOfWhiteSpace = (whiteSpace: TextNode) => {\r\n const selection = $createRangeSelection();\r\n const endOffset = whiteSpace.getTextContentSize();\r\n selection.setTextNodeRange(whiteSpace, endOffset, whiteSpace, endOffset);\r\n $setSelection(selection);\r\n };\r\n\r\n const isCursorBeforeLink = (anchorNode: LexicalNode, offset: number) =>\r\n $isTextNode(anchorNode) &&\r\n offset === anchorNode.getTextContentSize() &&\r\n anchorNode.getNextSibling() instanceof CourseCatalogueNode;\r\n\r\n const removeUnEditable = editor.registerCommand(\r\n KEY_DOWN_COMMAND,\r\n (event: KeyboardEvent) => {\r\n const selection = $getSelection();\r\n if ($isRangeSelection(selection)) {\r\n const key = event.key;\r\n const anchorNode = selection.anchor.getNode();\r\n const offset = selection.anchor.offset;\r\n let courseCatalogueLink = $getNearestNodeOfType(anchorNode, CourseCatalogueNode);\r\n\r\n // Detect if cursor is right before the link\r\n if (isCursorBeforeLink(anchorNode, offset)) {\r\n courseCatalogueLink = anchorNode.getNextSibling();\r\n }\r\n\r\n if (!courseCatalogueLink) {\r\n return false;\r\n }\r\n\r\n const nodeLength = courseCatalogueLink?.getTextContentSize();\r\n\r\n // Prevent Enter if in the middle of the link, allow only at start or end\r\n if (courseCatalogueLink && event.key === 'Enter') {\r\n event.preventDefault();\r\n editor.update(() => {\r\n if (isCursorBeforeLink(anchorNode, offset)) {\r\n const brNode = $createTextNode('\\n');\r\n courseCatalogueLink.insertBefore(brNode);\r\n }\r\n if (offset === nodeLength) {\r\n const brNode = $createTextNode('\\n');\r\n courseCatalogueLink.insertAfter(brNode);\r\n moveToEndOfWhiteSpace(brNode);\r\n }\r\n });\r\n return true;\r\n }\r\n\r\n // Allow add space before or after the link\r\n if (courseCatalogueLink && (key === ' ' || event.code === 'Space')) {\r\n event.preventDefault();\r\n editor.update(() => {\r\n const spaceToAdd = $createTextNode(' ');\r\n if (isCursorBeforeLink(anchorNode, offset)) {\r\n courseCatalogueLink.insertBefore(spaceToAdd);\r\n moveToEndOfWhiteSpace(spaceToAdd);\r\n }\r\n if (offset === nodeLength) {\r\n courseCatalogueLink.insertAfter(spaceToAdd);\r\n moveToEndOfWhiteSpace(spaceToAdd);\r\n }\r\n });\r\n return true;\r\n }\r\n\r\n // Delete link if selected and Backspace or Del is pressed\r\n if (courseCatalogueLink && (key === 'Backspace' || key === 'Delete')) {\r\n event.preventDefault();\r\n editor.update(\r\n () => {\r\n editor.dispatchCommand(REMOVE_COURSE_CATALOGUE_LINK, undefined);\r\n },\r\n { discrete: true }\r\n );\r\n return true;\r\n }\r\n\r\n // Allow Home, End and Arrow navigation\r\n if (\r\n courseCatalogueLink &&\r\n key !== 'ArrowLeft' &&\r\n key !== 'ArrowRight' &&\r\n key !== 'ArrowUp' &&\r\n key !== 'ArrowDown' &&\r\n key !== 'Home' &&\r\n key !== 'End' &&\r\n !(event.ctrlKey && (key.toLowerCase() === 'z' || key.toLowerCase() === 'y')) &&\r\n !(event.ctrlKey && key.toLowerCase() === 'c')\r\n ) {\r\n event.preventDefault();\r\n return true;\r\n }\r\n }\r\n return false;\r\n },\r\n COMMAND_PRIORITY_CRITICAL\r\n );\r\n\r\n const removeCopy = editor.registerCommand(\r\n COPY_COMMAND,\r\n (event: ClipboardEvent) => {\r\n const selection = $getSelection();\r\n if ($isRangeSelection(selection)) {\r\n const anchorNode = selection.anchor.getNode();\r\n const courseCatalogueLink = $getNearestNodeOfType(anchorNode, CourseCatalogueNode);\r\n if (courseCatalogueLink) {\r\n event.preventDefault();\r\n const domElement = editor.getElementByKey(courseCatalogueLink.getKey());\r\n if (domElement) {\r\n event.clipboardData?.setData('text/html', domElement.outerHTML);\r\n event.clipboardData?.setData('text/plain', courseCatalogueLink.getTextContent());\r\n }\r\n return true;\r\n }\r\n }\r\n return false;\r\n },\r\n COMMAND_PRIORITY_LOW\r\n );\r\n return () => {\r\n removeKeyboardShortcut();\r\n removeStatusListener();\r\n removeUnEditable();\r\n removeCopy();\r\n };\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [editor]);\r\n\r\n useOnClickOutside(flyoutRef as RefObject<HTMLElement>, () => setFlyoutPosition(null));\r\n\r\n const handleOnScroll = () => {\r\n closeFlyout();\r\n };\r\n\r\n useEffect(() => {\r\n return mergeRegister(\r\n editor.registerCommand(\r\n KEY_DOWN_COMMAND,\r\n (event: KeyboardEvent) => {\r\n if (event.key === 'Escape' && isVisibleRef.current) {\r\n event.preventDefault();\r\n closeFlyout();\r\n return true;\r\n }\r\n return false;\r\n },\r\n COMMAND_PRIORITY_LOW\r\n ),\r\n\r\n editor.registerRootListener((rootElement, prevRootElement) => {\r\n if (prevRootElement) {\r\n prevRootElement.removeEventListener('scroll', handleOnScroll);\r\n }\r\n\r\n if (rootElement) {\r\n rootElement.addEventListener('scroll', handleOnScroll);\r\n }\r\n })\r\n );\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [editor]);\r\n\r\n useEffect(() => {\r\n if (flyoutPosition) {\r\n closeFlyout();\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [parentScrollPosition]);\r\n\r\n return (\r\n <div className={styles['editor__toolbar-button-group']}>\r\n <div className={styles['editor__toolbar-button-flyoutwrapper']}>\r\n <div className={styles['editor__toolbar-button-group--text']}>\r\n <button\r\n onClick={() => openFlyout('course')}\r\n title={t.cataloguelinks.courseTooltip}\r\n className={clsx(\r\n styles['editor__toolbar-button'],\r\n styles['editor__toolbar-button--text'],\r\n courseIsActive && styles[`editor__toolbar-button--active`]\r\n )}\r\n aria-label={t.aria.labels.courselink}\r\n aria-keyshortcuts={t.aria.keyshortcuts.courselink}\r\n type=\"button\"\r\n ref={courseButtonRef}\r\n >\r\n {t.cataloguelinks.courseButtonLabel}\r\n </button>\r\n <button\r\n onClick={() => openFlyout('programme')}\r\n title={t.cataloguelinks.programmeTooltip}\r\n className={clsx(\r\n styles['editor__toolbar-button'],\r\n styles['editor__toolbar-button--text'],\r\n programmeIsActive && styles[`editor__toolbar-button--active`]\r\n )}\r\n aria-label={t.aria.labels.programmelink}\r\n aria-keyshortcuts={t.aria.keyshortcuts.programmelink}\r\n type=\"button\"\r\n ref={programmeButtonRef}\r\n >\r\n {t.cataloguelinks.programmeButtonLabel}\r\n </button>\r\n </div>\r\n {flyoutPosition && (\r\n <div\r\n className={styles['editor__toolbar-flyout-wrapper']}\r\n style={{ top: flyoutPosition.top, left: flyoutPosition.left }}\r\n ref={flyoutRef}\r\n >\r\n <AddCatalogueLinkForm\r\n linkType={type}\r\n onCloseHandler={closeFlyout}\r\n onSearchHandler={onSearch}\r\n searchResponse={searchResponse}\r\n onSelect={(code, label, linkType) => {\r\n editor.dispatchCommand(INSERT_COURSE_CATALOGUE_LINK, {\r\n linkType,\r\n code,\r\n label,\r\n });\r\n closeFlyout();\r\n }}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n};\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CourseCataloguePlugin.js","names":[],"sources":["../../../../../src/components/RteEditor/Plugins/CourseCataloguePlugin/CourseCataloguePlugin.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\r\nimport { clsx } from 'clsx';\r\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\r\nimport {\r\n $createRangeSelection,\r\n $createTextNode,\r\n $getSelection,\r\n $isRangeSelection,\r\n $isTextNode,\r\n $setSelection,\r\n COMMAND_PRIORITY_CRITICAL,\r\n COMMAND_PRIORITY_LOW,\r\n COPY_COMMAND,\r\n KEY_DOWN_COMMAND,\r\n mergeRegister,\r\n} from 'lexical';\r\nimport { $getNearestNodeOfType } from '@lexical/utils';\r\n\r\nimport type { RefObject } from 'react';\r\nimport type { LexicalNode, TextNode } from 'lexical';\r\nimport type { SearchResponse } from './AddCatalogueLinkForm';\r\n\r\nimport { AddCatalogueLinkForm } from './AddCatalogueLinkForm';\r\n\r\nimport styles from 'components/RteEditor/RteEditor.module.css';\r\nimport { useTranslation } from 'components/RteEditor/hooks/useTranslation';\r\nimport {\r\n $getLinkTypeFromNode,\r\n CourseCatalogueNode,\r\n INSERT_COURSE_CATALOGUE_LINK,\r\n REMOVE_COURSE_CATALOGUE_LINK,\r\n} from 'components/RteEditor/nodes/CourseCatalogueNode';\r\nimport { useOnClickOutside } from 'components/hooks/useOnClickOutside';\r\n\r\ninterface CourseCataloguePluginProps {\r\n onSearch: (query: string, linkType: 'course' | 'programme') => void;\r\n searchResponse: SearchResponse;\r\n parentScrollPosition: number;\r\n}\r\n\r\nexport const CourseCataloguePlugin = ({\r\n onSearch,\r\n searchResponse,\r\n parentScrollPosition,\r\n}: CourseCataloguePluginProps) => {\r\n const [editor] = useLexicalComposerContext();\r\n const t = useTranslation();\r\n const [courseIsActive, setCourseIsActive] = useState(false);\r\n const [programmeIsActive, setProgrammeIsActive] = useState(false);\r\n const courseButtonRef = useRef<HTMLButtonElement>(null);\r\n const programmeButtonRef = useRef<HTMLButtonElement>(null);\r\n const flyoutRef = useRef<HTMLDivElement>(null);\r\n const [flyoutPosition, setFlyoutPosition] = useState<{ top: number; left: number } | null>(null);\r\n const [type, setType] = useState<'course' | 'programme'>('course');\r\n const isVisibleRef = useRef(flyoutPosition !== null);\r\n\r\n const openFlyout = (type: 'course' | 'programme') => {\r\n setType(type);\r\n const rect =\r\n type === 'course'\r\n ? courseButtonRef.current?.getBoundingClientRect()\r\n : programmeButtonRef.current?.getBoundingClientRect();\r\n if (rect) {\r\n setFlyoutPosition({ top: rect.bottom, left: rect.left });\r\n }\r\n };\r\n\r\n const closeFlyout = () => {\r\n onSearch('', type);\r\n setFlyoutPosition(null);\r\n };\r\n\r\n useEffect(() => {\r\n const removeKeyboardShortcut = editor.registerCommand(\r\n KEY_DOWN_COMMAND,\r\n (event: KeyboardEvent) => {\r\n if (event.ctrlKey && event.shiftKey && event.altKey && event.key === 'C') {\r\n event.preventDefault();\r\n openFlyout('course');\r\n return true;\r\n }\r\n if (event.ctrlKey && event.shiftKey && event.altKey && event.key === 'P') {\r\n event.preventDefault();\r\n openFlyout('programme');\r\n return true;\r\n }\r\n return false;\r\n },\r\n COMMAND_PRIORITY_CRITICAL\r\n );\r\n\r\n const removeStatusListener = editor.registerUpdateListener(({ editorState }) => {\r\n editorState.read(() => {\r\n const selection = $getSelection();\r\n if ($isRangeSelection(selection)) {\r\n const anchorNode = selection.anchor.getNode();\r\n const offset = selection.anchor.offset;\r\n\r\n if (\r\n $isTextNode(anchorNode) &&\r\n offset === anchorNode.getTextContentSize() &&\r\n anchorNode.getNextSibling() instanceof CourseCatalogueNode\r\n ) {\r\n // Cursor staat aan het begin van de link!\r\n const courseCatalogueLink = anchorNode.getNextSibling();\r\n if (courseCatalogueLink) {\r\n const linkType = $getLinkTypeFromNode(courseCatalogueLink);\r\n setCourseIsActive(linkType === 'course');\r\n setProgrammeIsActive(linkType === 'programme');\r\n return;\r\n }\r\n }\r\n\r\n const courseCatalogueLink = $getNearestNodeOfType(anchorNode, CourseCatalogueNode);\r\n if (courseCatalogueLink) {\r\n const linkType = $getLinkTypeFromNode(courseCatalogueLink);\r\n setCourseIsActive(linkType === 'course');\r\n setProgrammeIsActive(linkType === 'programme');\r\n return;\r\n }\r\n setCourseIsActive(false);\r\n setProgrammeIsActive(false);\r\n }\r\n });\r\n });\r\n\r\n const moveToEndOfWhiteSpace = (whiteSpace: TextNode) => {\r\n const selection = $createRangeSelection();\r\n const endOffset = whiteSpace.getTextContentSize();\r\n selection.setTextNodeRange(whiteSpace, endOffset, whiteSpace, endOffset);\r\n $setSelection(selection);\r\n };\r\n\r\n const isCursorBeforeLink = (anchorNode: LexicalNode, offset: number) =>\r\n $isTextNode(anchorNode) &&\r\n offset === anchorNode.getTextContentSize() &&\r\n anchorNode.getNextSibling() instanceof CourseCatalogueNode;\r\n\r\n const removeUnEditable = editor.registerCommand(\r\n KEY_DOWN_COMMAND,\r\n (event: KeyboardEvent) => {\r\n const selection = $getSelection();\r\n if ($isRangeSelection(selection)) {\r\n const key = event.key;\r\n const anchorNode = selection.anchor.getNode();\r\n const offset = selection.anchor.offset;\r\n let courseCatalogueLink = $getNearestNodeOfType(anchorNode, CourseCatalogueNode);\r\n\r\n // Detect if cursor is right before the link\r\n if (isCursorBeforeLink(anchorNode, offset)) {\r\n courseCatalogueLink = anchorNode.getNextSibling();\r\n }\r\n\r\n if (!courseCatalogueLink) {\r\n return false;\r\n }\r\n\r\n const nodeLength = courseCatalogueLink?.getTextContentSize();\r\n\r\n // Prevent Enter if in the middle of the link, allow only at start or end\r\n if (courseCatalogueLink && event.key === 'Enter') {\r\n event.preventDefault();\r\n editor.update(() => {\r\n if (isCursorBeforeLink(anchorNode, offset)) {\r\n const brNode = $createTextNode('\\n');\r\n courseCatalogueLink.insertBefore(brNode);\r\n }\r\n if (offset === nodeLength) {\r\n const brNode = $createTextNode('\\n');\r\n courseCatalogueLink.insertAfter(brNode);\r\n moveToEndOfWhiteSpace(brNode);\r\n }\r\n });\r\n return true;\r\n }\r\n\r\n // Allow add space before or after the link\r\n if (courseCatalogueLink && (key === ' ' || event.code === 'Space')) {\r\n event.preventDefault();\r\n editor.update(() => {\r\n const spaceToAdd = $createTextNode(' ');\r\n if (isCursorBeforeLink(anchorNode, offset)) {\r\n courseCatalogueLink.insertBefore(spaceToAdd);\r\n moveToEndOfWhiteSpace(spaceToAdd);\r\n }\r\n if (offset === nodeLength) {\r\n courseCatalogueLink.insertAfter(spaceToAdd);\r\n moveToEndOfWhiteSpace(spaceToAdd);\r\n }\r\n });\r\n return true;\r\n }\r\n\r\n // Delete link if selected and Backspace or Del is pressed\r\n if (courseCatalogueLink && (key === 'Backspace' || key === 'Delete')) {\r\n event.preventDefault();\r\n editor.update(\r\n () => {\r\n editor.dispatchCommand(REMOVE_COURSE_CATALOGUE_LINK, undefined);\r\n },\r\n { discrete: true }\r\n );\r\n return true;\r\n }\r\n\r\n // Allow Home, End and Arrow navigation\r\n if (\r\n courseCatalogueLink &&\r\n key !== 'ArrowLeft' &&\r\n key !== 'ArrowRight' &&\r\n key !== 'ArrowUp' &&\r\n key !== 'ArrowDown' &&\r\n key !== 'Home' &&\r\n key !== 'End' &&\r\n !(event.ctrlKey && (key.toLowerCase() === 'z' || key.toLowerCase() === 'y')) &&\r\n !(event.ctrlKey && key.toLowerCase() === 'c')\r\n ) {\r\n event.preventDefault();\r\n return true;\r\n }\r\n }\r\n return false;\r\n },\r\n COMMAND_PRIORITY_CRITICAL\r\n );\r\n\r\n const removeCopy = editor.registerCommand(\r\n COPY_COMMAND,\r\n (event: ClipboardEvent) => {\r\n const selection = $getSelection();\r\n if ($isRangeSelection(selection)) {\r\n const anchorNode = selection.anchor.getNode();\r\n const courseCatalogueLink = $getNearestNodeOfType(anchorNode, CourseCatalogueNode);\r\n if (courseCatalogueLink) {\r\n event.preventDefault();\r\n const domElement = editor.getElementByKey(courseCatalogueLink.getKey());\r\n if (domElement) {\r\n event.clipboardData?.setData('text/html', domElement.outerHTML);\r\n event.clipboardData?.setData('text/plain', courseCatalogueLink.getTextContent());\r\n }\r\n return true;\r\n }\r\n }\r\n return false;\r\n },\r\n COMMAND_PRIORITY_LOW\r\n );\r\n return () => {\r\n removeKeyboardShortcut();\r\n removeStatusListener();\r\n removeUnEditable();\r\n removeCopy();\r\n };\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [editor]);\r\n\r\n useOnClickOutside(flyoutRef as RefObject<HTMLElement>, () => setFlyoutPosition(null));\r\n\r\n const handleOnScroll = () => {\r\n closeFlyout();\r\n };\r\n\r\n useEffect(() => {\r\n return mergeRegister(\r\n editor.registerCommand(\r\n KEY_DOWN_COMMAND,\r\n (event: KeyboardEvent) => {\r\n if (event.key === 'Escape' && isVisibleRef.current) {\r\n event.preventDefault();\r\n closeFlyout();\r\n return true;\r\n }\r\n return false;\r\n },\r\n COMMAND_PRIORITY_LOW\r\n ),\r\n\r\n editor.registerRootListener((rootElement, prevRootElement) => {\r\n if (prevRootElement) {\r\n prevRootElement.removeEventListener('scroll', handleOnScroll);\r\n }\r\n\r\n if (rootElement) {\r\n rootElement.addEventListener('scroll', handleOnScroll);\r\n }\r\n })\r\n );\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [editor]);\r\n\r\n useEffect(() => {\r\n if (flyoutPosition) {\r\n closeFlyout();\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [parentScrollPosition]);\r\n\r\n return (\r\n <div className={styles['editor__toolbar-button-group']}>\r\n <div className={styles['editor__toolbar-button-flyoutwrapper']}>\r\n <div className={styles['editor__toolbar-button-group--text']}>\r\n <button\r\n onClick={() => openFlyout('course')}\r\n title={t.cataloguelinks.courseTooltip}\r\n className={clsx(\r\n styles['editor__toolbar-button'],\r\n styles['editor__toolbar-button--text'],\r\n courseIsActive && styles[`editor__toolbar-button--active`]\r\n )}\r\n aria-label={t.aria.labels.courselink}\r\n aria-keyshortcuts={t.aria.keyshortcuts.courselink}\r\n type=\"button\"\r\n ref={courseButtonRef}\r\n >\r\n {t.cataloguelinks.courseButtonLabel}\r\n </button>\r\n <button\r\n onClick={() => openFlyout('programme')}\r\n title={t.cataloguelinks.programmeTooltip}\r\n className={clsx(\r\n styles['editor__toolbar-button'],\r\n styles['editor__toolbar-button--text'],\r\n programmeIsActive && styles[`editor__toolbar-button--active`]\r\n )}\r\n aria-label={t.aria.labels.programmelink}\r\n aria-keyshortcuts={t.aria.keyshortcuts.programmelink}\r\n type=\"button\"\r\n ref={programmeButtonRef}\r\n >\r\n {t.cataloguelinks.programmeButtonLabel}\r\n </button>\r\n </div>\r\n {flyoutPosition && (\r\n <div\r\n className={styles['editor__toolbar-flyout-wrapper']}\r\n style={{ top: flyoutPosition.top, left: flyoutPosition.left }}\r\n ref={flyoutRef}\r\n >\r\n <AddCatalogueLinkForm\r\n linkType={type}\r\n onCloseHandler={closeFlyout}\r\n onSearchHandler={onSearch}\r\n searchResponse={searchResponse}\r\n onSelect={(code, label, linkType) => {\r\n editor.dispatchCommand(INSERT_COURSE_CATALOGUE_LINK, {\r\n linkType,\r\n code,\r\n label,\r\n });\r\n closeFlyout();\r\n }}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n};\r\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ListPlugin.js","names":[],"sources":["../../../../../src/components/RteEditor/Plugins/ListPlugin/ListPlugin.tsx"],"sourcesContent":["import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n $createListNode,\n $isListItemNode,\n $isListNode,\n INSERT_ORDERED_LIST_COMMAND,\n INSERT_UNORDERED_LIST_COMMAND,\n ListNode,\n REMOVE_LIST_COMMAND,\n} from '@lexical/list';\nimport { useEffect, useState } from 'react';\nimport { clsx } from 'clsx';\nimport {\n $getSelection,\n $isRangeSelection,\n COMMAND_PRIORITY_CRITICAL,\n COMMAND_PRIORITY_LOW,\n KEY_DOWN_COMMAND,\n KEY_TAB_COMMAND,\n} from 'lexical';\nimport { $getNearestNodeOfType } from '@lexical/utils';\n\nimport type { RangeSelection } from 'lexical';\n\nimport { Icon } from 'components/Icon';\nimport styles from 'components/RteEditor/RteEditor.module.css';\nimport { useTranslation } from 'components/RteEditor/hooks/useTranslation';\n\ntype ListTypesType = 'bullet' | 'number' | null;\nconst LIST_TYPE_ICONS = {\n bullet: 'BulletList',\n number: 'NumberedList',\n};\n\nconst ListTypes = ['bullet', 'number'];\n\nexport const ListPlugin = () => {\n const t = useTranslation();\n const [editor] = useLexicalComposerContext();\n const [blockType, setBlockType] = useState<ListTypesType>(null);\n const [isUList, setIsUList] = useState<boolean>(false);\n const [isOList, setIsOList] = useState<boolean>(false);\n\n const formatList = (listType: ListTypesType): void => {\n if (listType === 'number' && blockType !== 'number') {\n editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);\n setBlockType('number');\n } else if (listType === 'bullet' && blockType !== 'bullet') {\n editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);\n setBlockType('bullet');\n } else {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);\n setBlockType(null);\n }\n };\n\n useEffect(() => {\n const removeKeyboardShortcut = editor.registerCommand(\n KEY_DOWN_COMMAND,\n (event: KeyboardEvent) => {\n if (event.ctrlKey && event.shiftKey && event.code === 'Digit7') {\n event.preventDefault();\n if (isOList) {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);\n } else {\n editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);\n }\n return true;\n }\n if (event.ctrlKey && event.shiftKey && event.code === 'Digit8') {\n event.preventDefault();\n if (isUList) {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);\n } else {\n editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);\n }\n return true;\n }\n return false;\n },\n COMMAND_PRIORITY_CRITICAL\n );\n\n return () => {\n removeKeyboardShortcut();\n };\n }, [editor, isOList, isUList]);\n\n useEffect(() => {\n const removeTabCommand = editor.registerCommand(\n KEY_TAB_COMMAND,\n (event) => {\n event.preventDefault();\n editor.update(() => {\n const selection = $getSelection() as RangeSelection;\n if (!$isRangeSelection(selection)) {\n return;\n }\n\n const currentNode = selection.anchor.getNode();\n const parent = currentNode.getParent();\n if (!$isListItemNode(parent)) {\n return;\n }\n\n const listParent = parent.getParent();\n if ($isListNode(listParent)) {\n const newList = $createListNode($isListNode(listParent) ? listParent.getListType() : 'bullet');\n parent.append(newList);\n newList.append(currentNode);\n }\n });\n return true;\n },\n COMMAND_PRIORITY_LOW\n );\n\n const removeStatusListener = editor.registerUpdateListener(({ editorState }) => {\n editorState.read(() => {\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n const anchorNode = selection.anchor.getNode();\n const listNode = $getNearestNodeOfType(anchorNode, ListNode);\n if (listNode) {\n const tag = listNode.getTag();\n setIsUList(tag === 'ul');\n setIsOList(tag === 'ol');\n if (tag === 'ul') {\n setBlockType('bullet');\n }\n if (tag === 'ol') {\n setBlockType('number');\n }\n return;\n }\n setIsUList(false);\n setIsOList(false);\n setBlockType(null);\n }\n return false;\n });\n });\n\n return () => {\n removeStatusListener();\n removeTabCommand();\n };\n }, [editor]);\n\n return (\n <div className={styles['editor__toolbar-button-group']}>\n {ListTypes.map((listType) => (\n <button\n onClick={() => formatList(listType as ListTypesType)}\n key={listType}\n title={t.format[`${listType}Tooltip` as keyof typeof t.format]}\n className={clsx(\n styles['editor__toolbar-button'],\n styles[`editor__toolbar-button--${listType}`],\n listType === 'bullet' && isUList && styles['editor__toolbar-button--active'],\n listType === 'number' && isOList && styles['editor__toolbar-button--active']\n )}\n aria-label={t.aria.labels[listType as keyof typeof t.aria.labels]}\n aria-keyshortcuts={t.aria.keyshortcuts[listType as keyof typeof t.aria.keyshortcuts]}\n type=\"button\"\n >\n <Icon name={LIST_TYPE_ICONS[listType as keyof typeof Icon]} size={24} />\n </button>\n ))}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;AA6BA,IAAM,IAAkB;CACtB,QAAQ;CACR,QAAQ;CACT,EAEK,IAAY,CAAC,UAAU,SAAS,EAEzB,UAAmB;CAC9B,IAAM,IAAI,GAAgB,EACpB,CAAC,KAAU,GAA2B,EACtC,CAAC,GAAW,KAAgB,EAAwB,KAAK,EACzD,CAAC,GAAS,KAAc,EAAkB,GAAM,EAChD,CAAC,GAAS,KAAc,EAAkB,GAAM,EAEhD,KAAc,MAAkC;
|
|
1
|
+
{"version":3,"file":"ListPlugin.js","names":[],"sources":["../../../../../src/components/RteEditor/Plugins/ListPlugin/ListPlugin.tsx"],"sourcesContent":["import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n $createListNode,\n $isListItemNode,\n $isListNode,\n INSERT_ORDERED_LIST_COMMAND,\n INSERT_UNORDERED_LIST_COMMAND,\n ListNode,\n REMOVE_LIST_COMMAND,\n} from '@lexical/list';\nimport { useEffect, useState } from 'react';\nimport { clsx } from 'clsx';\nimport {\n $getSelection,\n $isRangeSelection,\n COMMAND_PRIORITY_CRITICAL,\n COMMAND_PRIORITY_LOW,\n KEY_DOWN_COMMAND,\n KEY_TAB_COMMAND,\n} from 'lexical';\nimport { $getNearestNodeOfType } from '@lexical/utils';\n\nimport type { RangeSelection } from 'lexical';\n\nimport { Icon } from 'components/Icon';\nimport styles from 'components/RteEditor/RteEditor.module.css';\nimport { useTranslation } from 'components/RteEditor/hooks/useTranslation';\n\ntype ListTypesType = 'bullet' | 'number' | null;\nconst LIST_TYPE_ICONS = {\n bullet: 'BulletList',\n number: 'NumberedList',\n};\n\nconst ListTypes = ['bullet', 'number'];\n\nexport const ListPlugin = () => {\n const t = useTranslation();\n const [editor] = useLexicalComposerContext();\n const [blockType, setBlockType] = useState<ListTypesType>(null);\n const [isUList, setIsUList] = useState<boolean>(false);\n const [isOList, setIsOList] = useState<boolean>(false);\n\n const formatList = (listType: ListTypesType): void => {\n if (listType === 'number' && blockType !== 'number') {\n editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);\n setBlockType('number');\n } else if (listType === 'bullet' && blockType !== 'bullet') {\n editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);\n setBlockType('bullet');\n } else {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);\n setBlockType(null);\n }\n };\n\n useEffect(() => {\n const removeKeyboardShortcut = editor.registerCommand(\n KEY_DOWN_COMMAND,\n (event: KeyboardEvent) => {\n if (event.ctrlKey && event.shiftKey && event.code === 'Digit7') {\n event.preventDefault();\n if (isOList) {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);\n } else {\n editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);\n }\n return true;\n }\n if (event.ctrlKey && event.shiftKey && event.code === 'Digit8') {\n event.preventDefault();\n if (isUList) {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);\n } else {\n editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);\n }\n return true;\n }\n return false;\n },\n COMMAND_PRIORITY_CRITICAL\n );\n\n return () => {\n removeKeyboardShortcut();\n };\n }, [editor, isOList, isUList]);\n\n useEffect(() => {\n const removeTabCommand = editor.registerCommand(\n KEY_TAB_COMMAND,\n (event) => {\n event.preventDefault();\n editor.update(() => {\n const selection = $getSelection() as RangeSelection;\n if (!$isRangeSelection(selection)) {\n return;\n }\n\n const currentNode = selection.anchor.getNode();\n const parent = currentNode.getParent();\n if (!$isListItemNode(parent)) {\n return;\n }\n\n const listParent = parent.getParent();\n if ($isListNode(listParent)) {\n const newList = $createListNode($isListNode(listParent) ? listParent.getListType() : 'bullet');\n parent.append(newList);\n newList.append(currentNode);\n }\n });\n return true;\n },\n COMMAND_PRIORITY_LOW\n );\n\n const removeStatusListener = editor.registerUpdateListener(({ editorState }) => {\n editorState.read(() => {\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n const anchorNode = selection.anchor.getNode();\n const listNode = $getNearestNodeOfType(anchorNode, ListNode);\n if (listNode) {\n const tag = listNode.getTag();\n setIsUList(tag === 'ul');\n setIsOList(tag === 'ol');\n if (tag === 'ul') {\n setBlockType('bullet');\n }\n if (tag === 'ol') {\n setBlockType('number');\n }\n return;\n }\n setIsUList(false);\n setIsOList(false);\n setBlockType(null);\n }\n return false;\n });\n });\n\n return () => {\n removeStatusListener();\n removeTabCommand();\n };\n }, [editor]);\n\n return (\n <div className={styles['editor__toolbar-button-group']}>\n {ListTypes.map((listType) => (\n <button\n onClick={() => formatList(listType as ListTypesType)}\n key={listType}\n title={t.format[`${listType}Tooltip` as keyof typeof t.format]}\n className={clsx(\n styles['editor__toolbar-button'],\n styles[`editor__toolbar-button--${listType}`],\n listType === 'bullet' && isUList && styles['editor__toolbar-button--active'],\n listType === 'number' && isOList && styles['editor__toolbar-button--active']\n )}\n aria-label={t.aria.labels[listType as keyof typeof t.aria.labels]}\n aria-keyshortcuts={t.aria.keyshortcuts[listType as keyof typeof t.aria.keyshortcuts]}\n type=\"button\"\n >\n <Icon name={LIST_TYPE_ICONS[listType as keyof typeof Icon]} size={24} />\n </button>\n ))}\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","names":[],"sources":["../../../../../src/components/RteEditor/Plugins/TablePlugin/helpers.ts"],"sourcesContent":["import {\n $createTableNodeWithDimensions,\n $createTableRowNode,\n $createTableCellNode,\n $deleteTableColumnAtSelection,\n $isTableCellNode,\n $getTableNodeFromLexicalNodeOrThrow,\n $getTableRowNodeFromTableCellNodeOrThrow,\n $getTableRowIndexFromTableCellNode,\n $getTableColumnIndexFromTableCellNode,\n $insertTableColumnAtSelection,\n $insertTableRowAtSelection,\n $findTableNode,\n} from '@lexical/table';\nimport { $createParagraphNode } from 'lexical';\n\nimport type { TableCellNode, TableNode, TableRowNode } from '@lexical/table';\nimport type { TextNode, ElementNode, LexicalEditor } from 'lexical';\n\nimport { TableWrapperNode } from 'components/RteEditor/nodes';\n\nexport const MIN_COLUMN_WIDTH = 32;\nexport const DEFAULT_COL_WIDTH = 48;\nexport const BORDER_WIDTHS = 1;\nexport const PREVENT_OPEN_DELAY = 200;\nexport const DEFAULT_EDITOR_WIDTH = 320;\n\nexport const createTable = (nrOfRows: number, nrOfColumns: number): ElementNode => {\n const tableNode = $createTableNodeWithDimensions(0, 0, false);\n for (let rowIndex = 0; rowIndex < nrOfRows; rowIndex++) {\n const rowNode = $createTableRowNode();\n for (let colIndex = 0; colIndex < nrOfColumns; colIndex++) {\n const cellNode = $createTableCellNode(0, undefined, undefined);\n cellNode.append($createParagraphNode());\n rowNode.append(cellNode);\n }\n tableNode.append(rowNode);\n }\n return tableNode;\n};\n\nexport const deleteRow = (selectedNode: ElementNode) => {\n const currentRow = $getTableRowNodeFromTableCellNodeOrThrow(selectedNode);\n const nextRow = currentRow.getNextSibling() || currentRow.getPreviousSibling();\n const currentTable = currentRow.getParentOrThrow();\n currentTable.getChildrenSize() > 1 ? currentRow.remove() : currentTable.remove();\n\n if (nextRow !== null) {\n const firstDescendant = (nextRow as ElementNode).getFirstDescendant();\n if (firstDescendant) {\n (firstDescendant as TextNode).select();\n }\n }\n};\n\nexport const deleteTable = (selectedNode: ElementNode) => {\n const tableNode = $findTableNode(selectedNode);\n if (!tableNode) {\n throw new Error('Selected node is not a TableCellNode');\n }\n\n const wrapperNode = tableNode.getParent();\n if (wrapperNode instanceof TableWrapperNode) {\n wrapperNode.remove();\n } else {\n tableNode.remove();\n }\n};\n\nexport const insertRow = (selectedNode: ElementNode, position: 'insertRowAbove' | 'insertRowBelow') => {\n if (!$isTableCellNode(selectedNode)) {\n throw new Error('Selected node is not a TableCellNode');\n }\n const newRow = $createTableRowNode();\n\n $insertTableRowAtSelection(position === 'insertRowBelow');\n\n const firstDescendant = newRow.getFirstDescendant();\n if (firstDescendant) {\n (firstDescendant as TextNode).select();\n }\n};\n\nexport const insertColumn = (selectedNode: ElementNode, position: 'insertColumnLeft' | 'insertColumnRight') => {\n if (!$isTableCellNode(selectedNode)) {\n throw new Error('Selected node is not a TableCellNode');\n }\n const currentTable = $getTableNodeFromLexicalNodeOrThrow(selectedNode);\n let columnIndex = $getTableColumnIndexFromTableCellNode(selectedNode);\n const rowsInTable: TableCellNode[] = currentTable.getChildren();\n const rowIndex = $getTableRowIndexFromTableCellNode(selectedNode);\n const insertedCellNode = $insertTableColumnAtSelection(position === 'insertColumnLeft');\n\n if (!insertedCellNode) return;\n const insertedColumnIndex = $getTableColumnIndexFromTableCellNode(insertedCellNode);\n\n if (insertedColumnIndex === -1) return;\n const colWidths = currentTable.getColWidths();\n\n if (!colWidths) return;\n const newColWidths = colWidths.map((width, index) =>\n index === insertedColumnIndex ? DEFAULT_COL_WIDTH : width - Math.ceil(DEFAULT_COL_WIDTH / (colWidths.length - 1))\n );\n\n currentTable.setColWidths(newColWidths);\n\n columnIndex = position === 'insertColumnLeft' ? columnIndex : columnIndex + 1;\n const firstDescendant = rowsInTable[rowIndex].getChildren()[columnIndex];\n if (firstDescendant) {\n (firstDescendant as TextNode).select();\n }\n};\n\nexport const deleteColumn = (selectedNode: ElementNode) => {\n if (!$isTableCellNode(selectedNode)) {\n throw new Error('Selected node is not a TableCellNode');\n }\n const currentTable = $getTableNodeFromLexicalNodeOrThrow(selectedNode);\n const numberOfColumns = (currentTable.getFirstChild() as ElementNode)?.getChildrenSize() || 0;\n\n if (numberOfColumns === 1) {\n deleteTable(selectedNode);\n } else {\n $deleteTableColumnAtSelection();\n }\n};\n\nexport const getEditorContentWidth = (editor: LexicalEditor): number => {\n const rootEl = editor.getRootElement();\n if (!rootEl || typeof window === 'undefined') return 0;\n const rect = rootEl.getBoundingClientRect();\n const styles = window.getComputedStyle(rootEl);\n const insertX = parseFloat(styles.paddingLeft || '0') + parseFloat(styles.paddingRight || '0') + DEFAULT_COL_WIDTH;\n return Math.max(0, rect.width - insertX);\n};\n\nexport const getEditorParrentCellWidth = (\n node: TableCellNode | null,\n nrOfColumns: number,\n editor: LexicalEditor\n): number => {\n if (!node) return 0;\n\n const cell = editor.getElementByKey(node.getKey());\n if (!cell) return 0;\n\n const computedStyles = window.getComputedStyle(cell);\n return parseInt(computedStyles.width) - nrOfColumns * BORDER_WIDTHS - 1;\n};\n\nexport const tableHasContent = (tableNode: TableNode): boolean => {\n const rows = tableNode.getChildren();\n for (const row of rows) {\n const cells = (row as TableRowNode).getChildren();\n for (const cell of cells) {\n if ($isTableCellNode(cell)) {\n const cellText = cell.getTextContent().trim();\n if (cellText.length > 0) {\n return true;\n }\n }\n }\n }\n return false;\n};\n"],"mappings":";;;;AAqBA,IAAa,IAAmB,IACnB,IAAoB,IACpB,IAAgB,GAChB,IAAqB,KACrB,IAAuB,KAEvB,KAAe,GAAkB,MAAqC;CACjF,IAAM,IAAY,EAA+B,GAAG,GAAG,GAAM;
|
|
1
|
+
{"version":3,"file":"helpers.js","names":[],"sources":["../../../../../src/components/RteEditor/Plugins/TablePlugin/helpers.ts"],"sourcesContent":["import {\n $createTableNodeWithDimensions,\n $createTableRowNode,\n $createTableCellNode,\n $deleteTableColumnAtSelection,\n $isTableCellNode,\n $getTableNodeFromLexicalNodeOrThrow,\n $getTableRowNodeFromTableCellNodeOrThrow,\n $getTableRowIndexFromTableCellNode,\n $getTableColumnIndexFromTableCellNode,\n $insertTableColumnAtSelection,\n $insertTableRowAtSelection,\n $findTableNode,\n} from '@lexical/table';\nimport { $createParagraphNode } from 'lexical';\n\nimport type { TableCellNode, TableNode, TableRowNode } from '@lexical/table';\nimport type { TextNode, ElementNode, LexicalEditor } from 'lexical';\n\nimport { TableWrapperNode } from 'components/RteEditor/nodes';\n\nexport const MIN_COLUMN_WIDTH = 32;\nexport const DEFAULT_COL_WIDTH = 48;\nexport const BORDER_WIDTHS = 1;\nexport const PREVENT_OPEN_DELAY = 200;\nexport const DEFAULT_EDITOR_WIDTH = 320;\n\nexport const createTable = (nrOfRows: number, nrOfColumns: number): ElementNode => {\n const tableNode = $createTableNodeWithDimensions(0, 0, false);\n for (let rowIndex = 0; rowIndex < nrOfRows; rowIndex++) {\n const rowNode = $createTableRowNode();\n for (let colIndex = 0; colIndex < nrOfColumns; colIndex++) {\n const cellNode = $createTableCellNode(0, undefined, undefined);\n cellNode.append($createParagraphNode());\n rowNode.append(cellNode);\n }\n tableNode.append(rowNode);\n }\n return tableNode;\n};\n\nexport const deleteRow = (selectedNode: ElementNode) => {\n const currentRow = $getTableRowNodeFromTableCellNodeOrThrow(selectedNode);\n const nextRow = currentRow.getNextSibling() || currentRow.getPreviousSibling();\n const currentTable = currentRow.getParentOrThrow();\n currentTable.getChildrenSize() > 1 ? currentRow.remove() : currentTable.remove();\n\n if (nextRow !== null) {\n const firstDescendant = (nextRow as ElementNode).getFirstDescendant();\n if (firstDescendant) {\n (firstDescendant as TextNode).select();\n }\n }\n};\n\nexport const deleteTable = (selectedNode: ElementNode) => {\n const tableNode = $findTableNode(selectedNode);\n if (!tableNode) {\n throw new Error('Selected node is not a TableCellNode');\n }\n\n const wrapperNode = tableNode.getParent();\n if (wrapperNode instanceof TableWrapperNode) {\n wrapperNode.remove();\n } else {\n tableNode.remove();\n }\n};\n\nexport const insertRow = (selectedNode: ElementNode, position: 'insertRowAbove' | 'insertRowBelow') => {\n if (!$isTableCellNode(selectedNode)) {\n throw new Error('Selected node is not a TableCellNode');\n }\n const newRow = $createTableRowNode();\n\n $insertTableRowAtSelection(position === 'insertRowBelow');\n\n const firstDescendant = newRow.getFirstDescendant();\n if (firstDescendant) {\n (firstDescendant as TextNode).select();\n }\n};\n\nexport const insertColumn = (selectedNode: ElementNode, position: 'insertColumnLeft' | 'insertColumnRight') => {\n if (!$isTableCellNode(selectedNode)) {\n throw new Error('Selected node is not a TableCellNode');\n }\n const currentTable = $getTableNodeFromLexicalNodeOrThrow(selectedNode);\n let columnIndex = $getTableColumnIndexFromTableCellNode(selectedNode);\n const rowsInTable: TableCellNode[] = currentTable.getChildren();\n const rowIndex = $getTableRowIndexFromTableCellNode(selectedNode);\n const insertedCellNode = $insertTableColumnAtSelection(position === 'insertColumnLeft');\n\n if (!insertedCellNode) return;\n const insertedColumnIndex = $getTableColumnIndexFromTableCellNode(insertedCellNode);\n\n if (insertedColumnIndex === -1) return;\n const colWidths = currentTable.getColWidths();\n\n if (!colWidths) return;\n const newColWidths = colWidths.map((width, index) =>\n index === insertedColumnIndex ? DEFAULT_COL_WIDTH : width - Math.ceil(DEFAULT_COL_WIDTH / (colWidths.length - 1))\n );\n\n currentTable.setColWidths(newColWidths);\n\n columnIndex = position === 'insertColumnLeft' ? columnIndex : columnIndex + 1;\n const firstDescendant = rowsInTable[rowIndex].getChildren()[columnIndex];\n if (firstDescendant) {\n (firstDescendant as TextNode).select();\n }\n};\n\nexport const deleteColumn = (selectedNode: ElementNode) => {\n if (!$isTableCellNode(selectedNode)) {\n throw new Error('Selected node is not a TableCellNode');\n }\n const currentTable = $getTableNodeFromLexicalNodeOrThrow(selectedNode);\n const numberOfColumns = (currentTable.getFirstChild() as ElementNode)?.getChildrenSize() || 0;\n\n if (numberOfColumns === 1) {\n deleteTable(selectedNode);\n } else {\n $deleteTableColumnAtSelection();\n }\n};\n\nexport const getEditorContentWidth = (editor: LexicalEditor): number => {\n const rootEl = editor.getRootElement();\n if (!rootEl || typeof window === 'undefined') return 0;\n const rect = rootEl.getBoundingClientRect();\n const styles = window.getComputedStyle(rootEl);\n const insertX = parseFloat(styles.paddingLeft || '0') + parseFloat(styles.paddingRight || '0') + DEFAULT_COL_WIDTH;\n return Math.max(0, rect.width - insertX);\n};\n\nexport const getEditorParrentCellWidth = (\n node: TableCellNode | null,\n nrOfColumns: number,\n editor: LexicalEditor\n): number => {\n if (!node) return 0;\n\n const cell = editor.getElementByKey(node.getKey());\n if (!cell) return 0;\n\n const computedStyles = window.getComputedStyle(cell);\n return parseInt(computedStyles.width) - nrOfColumns * BORDER_WIDTHS - 1;\n};\n\nexport const tableHasContent = (tableNode: TableNode): boolean => {\n const rows = tableNode.getChildren();\n for (const row of rows) {\n const cells = (row as TableRowNode).getChildren();\n for (const cell of cells) {\n if ($isTableCellNode(cell)) {\n const cellText = cell.getTextContent().trim();\n if (cellText.length > 0) {\n return true;\n }\n }\n }\n }\n return false;\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LanguageProvider.js","names":[],"sources":["../../../../src/components/RteEditor/Providers/LanguageProvider.tsx"],"sourcesContent":["import { createContext, useContext, useState } from 'react';\n\nimport type { ReactNode } from 'react';\n\ninterface LanguageContextProps {\n currentLanguage: 'NL' | 'EN';\n switchLanguage: (currentLanguage: 'NL' | 'EN') => void;\n}\n\nconst LanguageContext = createContext<LanguageContextProps | undefined>(undefined);\n\nexport const LanguageProvider = ({ children }: { children: ReactNode }) => {\n const [currentLanguage, setCurrentLanguage] = useState<'NL' | 'EN'>('EN');\n\n const switchLanguage = (currentLanguage: 'NL' | 'EN') => {\n setCurrentLanguage(currentLanguage);\n };\n\n return <LanguageContext.Provider value={{ currentLanguage, switchLanguage }}>{children}</LanguageContext.Provider>;\n};\n\nexport const useLanguage = (): LanguageContextProps => {\n const context = useContext(LanguageContext);\n if (!context) {\n throw new Error('useLanguage must be used within a LanguageProvider');\n }\n return context;\n};\n"],"mappings":";;;AASA,IAAM,IAAkB,EAAgD,KAAA,EAAU,EAErE,KAAoB,EAAE,kBAAwC;CACzE,IAAM,CAAC,GAAiB,KAAsB,EAAsB,KAAK;
|
|
1
|
+
{"version":3,"file":"LanguageProvider.js","names":[],"sources":["../../../../src/components/RteEditor/Providers/LanguageProvider.tsx"],"sourcesContent":["import { createContext, useContext, useState } from 'react';\n\nimport type { ReactNode } from 'react';\n\ninterface LanguageContextProps {\n currentLanguage: 'NL' | 'EN';\n switchLanguage: (currentLanguage: 'NL' | 'EN') => void;\n}\n\nconst LanguageContext = createContext<LanguageContextProps | undefined>(undefined);\n\nexport const LanguageProvider = ({ children }: { children: ReactNode }) => {\n const [currentLanguage, setCurrentLanguage] = useState<'NL' | 'EN'>('EN');\n\n const switchLanguage = (currentLanguage: 'NL' | 'EN') => {\n setCurrentLanguage(currentLanguage);\n };\n\n return <LanguageContext.Provider value={{ currentLanguage, switchLanguage }}>{children}</LanguageContext.Provider>;\n};\n\nexport const useLanguage = (): LanguageContextProps => {\n const context = useContext(LanguageContext);\n if (!context) {\n throw new Error('useLanguage must be used within a LanguageProvider');\n }\n return context;\n};\n"],"mappings":";;;AASA,IAAM,IAAkB,EAAgD,KAAA,EAAU,EAErE,KAAoB,EAAE,kBAAwC;CACzE,IAAM,CAAC,GAAiB,KAAsB,EAAsB,KAAK;CAMzE,OAAO,kBAAC,EAAgB,UAAjB;EAA0B,OAAO;GAAE;GAAiB,iBAJnC,MAAiC;IACvD,EAAmB,EAAgB;;GAGsC;EAAG;EAAoC,CAAA;GAGvG,UAA0C;CACrD,IAAM,IAAU,EAAW,EAAgB;CAC3C,IAAI,CAAC,GACH,MAAU,MAAM,qDAAqD;CAEvE,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RteEditor.stories.js","names":[],"sources":["../../../src/components/RteEditor/RteEditor.stories.tsx"],"sourcesContent":["import { useRef, useState } from 'react';\n\nimport type { PropsWithChildren } from 'react';\nimport type { Meta, StoryFn } from '@storybook/react';\nimport type { RteEditorProps } from './RteEditor';\nimport type { SearchResponse } from './Plugins/CourseCataloguePlugin/AddCatalogueLinkForm';\n\nimport { RteEditor } from './RteEditor';\nimport { MOCK_RTE_CONTENT } from './mockRteContent';\nimport { MOCK_SEARCH_COURSES, MOCK_SEARCH_PROGRAMMES } from './mockCatalogueSearchData';\n\nimport { Container } from 'storyComponents/Container';\n\nconst QUERY_SPEED = 1000; // ms\nconst CHARACTER_THRESHOLD = 3;\n\nconst codeString = `<RteEditor\n editorId=\"editor-id\"\n initialValue=\"\"\n currentLanguage=\"NL\"\n label=\"\"\n info=\"\"\n placeholder=\"\"\n notValidatedText=\"\"\n onChange={handleChange}\n onCatalogueLinkSearch={handleCatalogueLinkSearch}\n catalogueSearchResponse={{ state: 'idle', results: [] }}\n />`;\n\n// eslint-disable-next-line import/no-default-export\nexport default {\n title: 'Organisms/RteEditor',\n component: RteEditor,\n parameters: {\n inspectComponent: RteEditor,\n codeString: codeString,\n },\n} as Meta<PropsWithChildren<RteEditorProps>>;\n\nconst Template: StoryFn<PropsWithChildren<RteEditorProps>> = (args) => {\n const [result, setResult] = useState<string>(args.initialValue || '');\n const [catalogueSearchResponse, setCatalogueSearchResponse] = useState<SearchResponse>({\n state: 'idle',\n results: [],\n });\n const networkTimer = useRef<NodeJS.Timeout | null>(null);\n\n const handleSearch = (query: string, linkType: 'course' | 'programme') => {\n if (query.length < CHARACTER_THRESHOLD) {\n clearTimeout(networkTimer.current!);\n setCatalogueSearchResponse({ state: 'idle', results: [] });\n return;\n }\n\n if (networkTimer.current !== null) {\n clearTimeout(networkTimer.current);\n }\n\n const lowerCaseQuery = query.toLowerCase();\n if (query.length >= CHARACTER_THRESHOLD) {\n setCatalogueSearchResponse({ state: 'pending', results: [] });\n const mockResults =\n linkType === 'course'\n ? MOCK_SEARCH_COURSES.filter(\n (item) =>\n item.name.NL.toLowerCase().includes(lowerCaseQuery) || item.code.toLowerCase().includes(lowerCaseQuery)\n )\n : MOCK_SEARCH_PROGRAMMES.filter(\n (item) =>\n item.name.NL.toLowerCase().includes(lowerCaseQuery) || item.code.toLowerCase().includes(lowerCaseQuery)\n );\n\n networkTimer.current = setTimeout(\n () =>\n setCatalogueSearchResponse({\n state: 'ready',\n results: mockResults,\n }),\n QUERY_SPEED\n );\n }\n };\n\n return (\n <>\n <Container size=\"large-full-height\">\n <RteEditor\n {...args}\n onChange={(evt) => setResult(evt)}\n onCatalogueLinkSearch={handleSearch}\n catalogueSearchResponse={catalogueSearchResponse}\n />\n </Container>\n <br />\n <br />\n\n <p style={{ margin: '0', marginTop: '2rem' }}>HTML Output:</p>\n <div\n style={{\n marginTop: '0rem',\n padding: '1rem',\n backgroundColor: '#F9F9F9',\n borderRadius: '0.25rem',\n color: '#666',\n }}\n >\n {result}\n </div>\n </>\n );\n};\n\nexport const RteEditorExample = Template.bind({});\n\nRteEditorExample.args = {\n editorId: 'test-editor',\n placeholder: 'Voeg hier tekst in...',\n currentLanguage: 'NL',\n label: 'Studiemateriaal',\n info: \"Studiemateriaal is essentieel voor succesvol leren. Het omvat boeken, artikelen, video's en oefeningen die studenten helpen hun kennis te vergroten, vaardigheden te ontwikkelen en hun studieprestaties te verbeteren.\",\n required: true,\n initialValue: MOCK_RTE_CONTENT,\n};\n\nexport const MultipleRteEditors = () => {\n const [result01, setResult01] = useState<string>(\n 'Students will:<br>• demonstrate digital literacy in an academic context<br>• learn to read and engage with texts from a range of disciplinary perspectives<br>• develop writing and argumentation skills appropriate to different disciplines<br>• learn to recognize and apply different research methodologies<br>• learn how to recognize and practice different genres and modes of academic discourse<br>• develop vocabulary appropriate to an academic environment<br>• improve analytic and critical thinking skills<br>• work independently and as part of a collaborative group<br>• learn to review and critique their own work and that of their peers <br>• improve listening comprehension and develop presentation skills<br>• participate in discussions, workshops and debates'\n );\n const [result02, setResult02] = useState<string>(\n `<p>Editor 2</p>\n <ul>\n <li>nesting</li>\n <li>\n <ol>\n <li>nested 1</li>\n <li>nested 2</li>\n </ol>\n </li>\n <li>nesting 2</li>\n <li>\n <ul>\n <li>deep nested 1</li>\n <li>deep nested 2</li>\n <li>\n <ol>\n <li>deeper nested 1</li>\n <li>\n <ul>\n <li>deepest nested 1</li>\n <li>deepest nested 2</li>\n </ul>\n </li>\n <li>deeper nested 2</li>\n <li>\n <ol>\n <li>deepest nested 1</li>\n <li>deepest nested 2</li>\n </ol>\n </li>\n </ol>\n </li>\n </ul>\n </li>\n <li>nesting end</li>\n </ul>`\n );\n\n return (\n <div\n style={{\n display: 'flex',\n flexDirection: 'row',\n gap: '1rem',\n width: '100%',\n padding: '1rem',\n backgroundColor: '#FFF',\n }}\n >\n <div style={{ flex: '1' }}>\n <RteEditor\n initialValue={result01}\n editorId=\"editor-one\"\n label=\"Editor 1\"\n info=\"Uitleg over editor 1\"\n placeholder=\"Voeg hier tekst in...\"\n notValidatedText=\"\"\n onChange={(evt) => setResult01(evt)}\n />\n <br />\n <p style={{ margin: '0', marginTop: '2rem' }}>HTML Output:</p>\n <div\n style={{\n marginTop: '0rem',\n padding: '1rem',\n backgroundColor: '#F9F9F9',\n borderRadius: '0.25rem',\n color: '#666',\n }}\n >\n {result01}\n </div>\n </div>\n <div style={{ flex: '1' }}>\n <RteEditor\n initialValue={result02}\n editorId=\"editor-two\"\n label=\"Editor 2\"\n info=\"Uitleg over editor 2 wat langer om te kijken of dat ook goed gaat, want je weet maar nooit.\"\n placeholder=\"Voeg hier tekst in...\"\n notValidatedText=\"\"\n onChange={(evt) => setResult02(evt)}\n />\n <br />\n <p style={{ margin: '0', marginTop: '2rem' }}>HTML Output:</p>\n <div\n style={{\n marginTop: '0rem',\n padding: '1rem',\n backgroundColor: '#F9F9F9',\n borderRadius: '0.25rem',\n color: '#666',\n }}\n >\n {result02}\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;;;AAaA,IAAM,IAAc,KACd,IAAsB,GAgB5B,IAAe;CACb,OAAO;CACP,WAAW;CACX,YAAY;EACV,kBAAkB;EACN;EACb;CACF,EA2EY,MAzEiD,MAAS;CACrE,IAAM,CAAC,GAAQ,KAAa,EAAiB,EAAK,gBAAgB,GAAG,EAC/D,CAAC,GAAyB,KAA8B,EAAyB;EACrF,OAAO;EACP,SAAS,EAAE;EACZ,CAAC,EACI,IAAe,EAA8B,KAAK,EAElD,KAAgB,GAAe,MAAqC;
|
|
1
|
+
{"version":3,"file":"RteEditor.stories.js","names":[],"sources":["../../../src/components/RteEditor/RteEditor.stories.tsx"],"sourcesContent":["import { useRef, useState } from 'react';\n\nimport type { PropsWithChildren } from 'react';\nimport type { Meta, StoryFn } from '@storybook/react';\nimport type { RteEditorProps } from './RteEditor';\nimport type { SearchResponse } from './Plugins/CourseCataloguePlugin/AddCatalogueLinkForm';\n\nimport { RteEditor } from './RteEditor';\nimport { MOCK_RTE_CONTENT } from './mockRteContent';\nimport { MOCK_SEARCH_COURSES, MOCK_SEARCH_PROGRAMMES } from './mockCatalogueSearchData';\n\nimport { Container } from 'storyComponents/Container';\n\nconst QUERY_SPEED = 1000; // ms\nconst CHARACTER_THRESHOLD = 3;\n\nconst codeString = `<RteEditor\n editorId=\"editor-id\"\n initialValue=\"\"\n currentLanguage=\"NL\"\n label=\"\"\n info=\"\"\n placeholder=\"\"\n notValidatedText=\"\"\n onChange={handleChange}\n onCatalogueLinkSearch={handleCatalogueLinkSearch}\n catalogueSearchResponse={{ state: 'idle', results: [] }}\n />`;\n\n// eslint-disable-next-line import/no-default-export\nexport default {\n title: 'Organisms/RteEditor',\n component: RteEditor,\n parameters: {\n inspectComponent: RteEditor,\n codeString: codeString,\n },\n} as Meta<PropsWithChildren<RteEditorProps>>;\n\nconst Template: StoryFn<PropsWithChildren<RteEditorProps>> = (args) => {\n const [result, setResult] = useState<string>(args.initialValue || '');\n const [catalogueSearchResponse, setCatalogueSearchResponse] = useState<SearchResponse>({\n state: 'idle',\n results: [],\n });\n const networkTimer = useRef<NodeJS.Timeout | null>(null);\n\n const handleSearch = (query: string, linkType: 'course' | 'programme') => {\n if (query.length < CHARACTER_THRESHOLD) {\n clearTimeout(networkTimer.current!);\n setCatalogueSearchResponse({ state: 'idle', results: [] });\n return;\n }\n\n if (networkTimer.current !== null) {\n clearTimeout(networkTimer.current);\n }\n\n const lowerCaseQuery = query.toLowerCase();\n if (query.length >= CHARACTER_THRESHOLD) {\n setCatalogueSearchResponse({ state: 'pending', results: [] });\n const mockResults =\n linkType === 'course'\n ? MOCK_SEARCH_COURSES.filter(\n (item) =>\n item.name.NL.toLowerCase().includes(lowerCaseQuery) || item.code.toLowerCase().includes(lowerCaseQuery)\n )\n : MOCK_SEARCH_PROGRAMMES.filter(\n (item) =>\n item.name.NL.toLowerCase().includes(lowerCaseQuery) || item.code.toLowerCase().includes(lowerCaseQuery)\n );\n\n networkTimer.current = setTimeout(\n () =>\n setCatalogueSearchResponse({\n state: 'ready',\n results: mockResults,\n }),\n QUERY_SPEED\n );\n }\n };\n\n return (\n <>\n <Container size=\"large-full-height\">\n <RteEditor\n {...args}\n onChange={(evt) => setResult(evt)}\n onCatalogueLinkSearch={handleSearch}\n catalogueSearchResponse={catalogueSearchResponse}\n />\n </Container>\n <br />\n <br />\n\n <p style={{ margin: '0', marginTop: '2rem' }}>HTML Output:</p>\n <div\n style={{\n marginTop: '0rem',\n padding: '1rem',\n backgroundColor: '#F9F9F9',\n borderRadius: '0.25rem',\n color: '#666',\n }}\n >\n {result}\n </div>\n </>\n );\n};\n\nexport const RteEditorExample = Template.bind({});\n\nRteEditorExample.args = {\n editorId: 'test-editor',\n placeholder: 'Voeg hier tekst in...',\n currentLanguage: 'NL',\n label: 'Studiemateriaal',\n info: \"Studiemateriaal is essentieel voor succesvol leren. Het omvat boeken, artikelen, video's en oefeningen die studenten helpen hun kennis te vergroten, vaardigheden te ontwikkelen en hun studieprestaties te verbeteren.\",\n required: true,\n initialValue: MOCK_RTE_CONTENT,\n};\n\nexport const MultipleRteEditors = () => {\n const [result01, setResult01] = useState<string>(\n 'Students will:<br>• demonstrate digital literacy in an academic context<br>• learn to read and engage with texts from a range of disciplinary perspectives<br>• develop writing and argumentation skills appropriate to different disciplines<br>• learn to recognize and apply different research methodologies<br>• learn how to recognize and practice different genres and modes of academic discourse<br>• develop vocabulary appropriate to an academic environment<br>• improve analytic and critical thinking skills<br>• work independently and as part of a collaborative group<br>• learn to review and critique their own work and that of their peers <br>• improve listening comprehension and develop presentation skills<br>• participate in discussions, workshops and debates'\n );\n const [result02, setResult02] = useState<string>(\n `<p>Editor 2</p>\n <ul>\n <li>nesting</li>\n <li>\n <ol>\n <li>nested 1</li>\n <li>nested 2</li>\n </ol>\n </li>\n <li>nesting 2</li>\n <li>\n <ul>\n <li>deep nested 1</li>\n <li>deep nested 2</li>\n <li>\n <ol>\n <li>deeper nested 1</li>\n <li>\n <ul>\n <li>deepest nested 1</li>\n <li>deepest nested 2</li>\n </ul>\n </li>\n <li>deeper nested 2</li>\n <li>\n <ol>\n <li>deepest nested 1</li>\n <li>deepest nested 2</li>\n </ol>\n </li>\n </ol>\n </li>\n </ul>\n </li>\n <li>nesting end</li>\n </ul>`\n );\n\n return (\n <div\n style={{\n display: 'flex',\n flexDirection: 'row',\n gap: '1rem',\n width: '100%',\n padding: '1rem',\n backgroundColor: '#FFF',\n }}\n >\n <div style={{ flex: '1' }}>\n <RteEditor\n initialValue={result01}\n editorId=\"editor-one\"\n label=\"Editor 1\"\n info=\"Uitleg over editor 1\"\n placeholder=\"Voeg hier tekst in...\"\n notValidatedText=\"\"\n onChange={(evt) => setResult01(evt)}\n />\n <br />\n <p style={{ margin: '0', marginTop: '2rem' }}>HTML Output:</p>\n <div\n style={{\n marginTop: '0rem',\n padding: '1rem',\n backgroundColor: '#F9F9F9',\n borderRadius: '0.25rem',\n color: '#666',\n }}\n >\n {result01}\n </div>\n </div>\n <div style={{ flex: '1' }}>\n <RteEditor\n initialValue={result02}\n editorId=\"editor-two\"\n label=\"Editor 2\"\n info=\"Uitleg over editor 2 wat langer om te kijken of dat ook goed gaat, want je weet maar nooit.\"\n placeholder=\"Voeg hier tekst in...\"\n notValidatedText=\"\"\n onChange={(evt) => setResult02(evt)}\n />\n <br />\n <p style={{ margin: '0', marginTop: '2rem' }}>HTML Output:</p>\n <div\n style={{\n marginTop: '0rem',\n padding: '1rem',\n backgroundColor: '#F9F9F9',\n borderRadius: '0.25rem',\n color: '#666',\n }}\n >\n {result02}\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","names":[],"sources":["../../../src/components/RteEditor/helpers.ts"],"sourcesContent":["import { LinkNode } from '@lexical/link';\nimport { ListNode, ListItemNode } from '@lexical/list';\nimport { ParagraphNode, TextNode } from 'lexical';\nimport { TableCellNode } from '@lexical/table';\n\nimport type { DOMExportOutput, Klass, LexicalEditor, LexicalNode } from 'lexical';\n\nimport { CourseCatalogueNode } from './nodes';\n\nexport const mergeBoldStrongTags = (html: string): string => {\n let mergedHtml = html.replace(/<b><strong>/gi, '<strong>');\n mergedHtml = mergedHtml.replace(/<\\/strong><\\/b>/gi, '</strong>');\n return mergedHtml;\n};\n\nexport const cleanUpTable = (html: string): string =>\n html.replace(/<div[^>]*>\\s*(<table[\\s\\S]*?<\\/table>)\\s*<\\/div>/gi, '$1');\n\nexport const removeStylesExportDOM = (editor: LexicalEditor, target: LexicalNode): DOMExportOutput => {\n const output = target.exportDOM(editor);\n if (output && output.element instanceof HTMLElement) {\n for (const el of [output.element, ...output.element.querySelectorAll('[style],[class],[dir=\"ltr\"]')]) {\n el.removeAttribute('class');\n if (el.getAttribute('style')) {\n el.setAttribute('style', '');\n el.removeAttribute('style');\n }\n if (el.getAttribute('dir') === 'ltr') {\n el.removeAttribute('dir');\n }\n }\n }\n return output;\n};\n\nexport const exportMap = new Map<Klass<LexicalNode>, (editor: LexicalEditor, target: LexicalNode) => DOMExportOutput>([\n [ParagraphNode, removeStylesExportDOM],\n [TextNode, removeStylesExportDOM],\n [ListNode, removeStylesExportDOM],\n [ListItemNode, removeStylesExportDOM],\n [TableCellNode, removeStylesExportDOM],\n [LinkNode, removeStylesExportDOM],\n [CourseCatalogueNode, removeStylesExportDOM],\n]);\n\nexport const setScrollableContainers = (fn: (event: Event) => void) => {\n const scrollableContainers = document.querySelectorAll('*');\n scrollableContainers.forEach((container) => {\n if (container.scrollHeight > container.clientHeight) {\n container.addEventListener('scroll', fn);\n }\n });\n};\n\nexport const removeScrollableContainers = (fn: (event: Event) => void) => {\n const scrollableContainers = document.querySelectorAll('*');\n scrollableContainers.forEach((container) => {\n if (container.scrollHeight > container.clientHeight) {\n container.removeEventListener('scroll', fn);\n }\n });\n};\n"],"mappings":";;;;;;AASA,IAAa,KAAuB,MAAyB;CAC3D,IAAI,IAAa,EAAK,QAAQ,iBAAiB,WAAW;
|
|
1
|
+
{"version":3,"file":"helpers.js","names":[],"sources":["../../../src/components/RteEditor/helpers.ts"],"sourcesContent":["import { LinkNode } from '@lexical/link';\nimport { ListNode, ListItemNode } from '@lexical/list';\nimport { ParagraphNode, TextNode } from 'lexical';\nimport { TableCellNode } from '@lexical/table';\n\nimport type { DOMExportOutput, Klass, LexicalEditor, LexicalNode } from 'lexical';\n\nimport { CourseCatalogueNode } from './nodes';\n\nexport const mergeBoldStrongTags = (html: string): string => {\n let mergedHtml = html.replace(/<b><strong>/gi, '<strong>');\n mergedHtml = mergedHtml.replace(/<\\/strong><\\/b>/gi, '</strong>');\n return mergedHtml;\n};\n\nexport const cleanUpTable = (html: string): string =>\n html.replace(/<div[^>]*>\\s*(<table[\\s\\S]*?<\\/table>)\\s*<\\/div>/gi, '$1');\n\nexport const removeStylesExportDOM = (editor: LexicalEditor, target: LexicalNode): DOMExportOutput => {\n const output = target.exportDOM(editor);\n if (output && output.element instanceof HTMLElement) {\n for (const el of [output.element, ...output.element.querySelectorAll('[style],[class],[dir=\"ltr\"]')]) {\n el.removeAttribute('class');\n if (el.getAttribute('style')) {\n el.setAttribute('style', '');\n el.removeAttribute('style');\n }\n if (el.getAttribute('dir') === 'ltr') {\n el.removeAttribute('dir');\n }\n }\n }\n return output;\n};\n\nexport const exportMap = new Map<Klass<LexicalNode>, (editor: LexicalEditor, target: LexicalNode) => DOMExportOutput>([\n [ParagraphNode, removeStylesExportDOM],\n [TextNode, removeStylesExportDOM],\n [ListNode, removeStylesExportDOM],\n [ListItemNode, removeStylesExportDOM],\n [TableCellNode, removeStylesExportDOM],\n [LinkNode, removeStylesExportDOM],\n [CourseCatalogueNode, removeStylesExportDOM],\n]);\n\nexport const setScrollableContainers = (fn: (event: Event) => void) => {\n const scrollableContainers = document.querySelectorAll('*');\n scrollableContainers.forEach((container) => {\n if (container.scrollHeight > container.clientHeight) {\n container.addEventListener('scroll', fn);\n }\n });\n};\n\nexport const removeScrollableContainers = (fn: (event: Event) => void) => {\n const scrollableContainers = document.querySelectorAll('*');\n scrollableContainers.forEach((container) => {\n if (container.scrollHeight > container.clientHeight) {\n container.removeEventListener('scroll', fn);\n }\n });\n};\n"],"mappings":";;;;;;AASA,IAAa,KAAuB,MAAyB;CAC3D,IAAI,IAAa,EAAK,QAAQ,iBAAiB,WAAW;CAE1D,OADA,IAAa,EAAW,QAAQ,qBAAqB,YAAY,EAC1D;GAGI,KAAgB,MAC3B,EAAK,QAAQ,sDAAsD,KAAK,EAE7D,KAAyB,GAAuB,MAAyC;CACpG,IAAM,IAAS,EAAO,UAAU,EAAO;CACvC,IAAI,KAAU,EAAO,mBAAmB,aACtC,KAAK,IAAM,KAAM,CAAC,EAAO,SAAS,GAAG,EAAO,QAAQ,iBAAiB,gCAA8B,CAAC,EAMlG,AALA,EAAG,gBAAgB,QAAQ,EACvB,EAAG,aAAa,QAAQ,KAC1B,EAAG,aAAa,SAAS,GAAG,EAC5B,EAAG,gBAAgB,QAAQ,GAEzB,EAAG,aAAa,MAAM,KAAK,SAC7B,EAAG,gBAAgB,MAAM;CAI/B,OAAO;GAGI,IAAY,IAAI,IAAyF;CACpH,CAAC,GAAe,EAAsB;CACtC,CAAC,GAAU,EAAsB;CACjC,CAAC,GAAU,EAAsB;CACjC,CAAC,GAAc,EAAsB;CACrC,CAAC,GAAe,EAAsB;CACtC,CAAC,GAAU,EAAsB;CACjC,CAAC,GAAqB,EAAsB;CAC7C,CAAC,EAEW,KAA2B,MAA+B;CAErE,SADsC,iBAAiB,IACvD,CAAqB,SAAS,MAAc;EAC1C,AAAI,EAAU,eAAe,EAAU,gBACrC,EAAU,iBAAiB,UAAU,EAAG;GAE1C;GAGS,KAA8B,MAA+B;CAExE,SADsC,iBAAiB,IACvD,CAAqB,SAAS,MAAc;EAC1C,AAAI,EAAU,eAAe,EAAU,gBACrC,EAAU,oBAAoB,UAAU,EAAG;GAE7C"}
|