mirror of
https://github.com/strapi/strapi.git
synced 2025-11-16 10:07:55 +00:00
Merge branch 'main' into tests/drop16
This commit is contained in:
commit
af6ddbba9b
3
.github/actions/run-api-tests/action.yml
vendored
3
.github/actions/run-api-tests/action.yml
vendored
@ -6,6 +6,8 @@ inputs:
|
|||||||
required: true
|
required: true
|
||||||
runEE:
|
runEE:
|
||||||
description: 'Should run EE or CE tests'
|
description: 'Should run EE or CE tests'
|
||||||
|
jestOptions:
|
||||||
|
description: 'Jest options'
|
||||||
runs:
|
runs:
|
||||||
using: 'composite'
|
using: 'composite'
|
||||||
steps:
|
steps:
|
||||||
@ -13,4 +15,5 @@ runs:
|
|||||||
env:
|
env:
|
||||||
DB_OPTIONS: ${{ inputs.dbOptions }}
|
DB_OPTIONS: ${{ inputs.dbOptions }}
|
||||||
RUN_EE: ${{ inputs.runEE }}
|
RUN_EE: ${{ inputs.runEE }}
|
||||||
|
JEST_OPTIONS: ${{ inputs.jestOptions }}
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
3
.github/actions/run-api-tests/script.sh
vendored
3
.github/actions/run-api-tests/script.sh
vendored
@ -9,7 +9,8 @@ export ENV_PATH="$(pwd)/test-apps/api/.env"
|
|||||||
export JWT_SECRET="aSecret"
|
export JWT_SECRET="aSecret"
|
||||||
|
|
||||||
opts=($DB_OPTIONS)
|
opts=($DB_OPTIONS)
|
||||||
|
jestOptions=($JEST_OPTIONS)
|
||||||
|
|
||||||
yarn nx run-many --target=build --nx-ignore-cycles --skip-nx-cache
|
yarn nx run-many --target=build --nx-ignore-cycles --skip-nx-cache
|
||||||
yarn run test:generate-app --appPath=test-apps/api "${opts[@]}"
|
yarn run test:generate-app --appPath=test-apps/api "${opts[@]}"
|
||||||
yarn run test:api --no-generate-app
|
yarn run test:api --no-generate-app "${jestOptions[@]}"
|
||||||
|
|||||||
28
.github/workflows/tests.yml
vendored
28
.github/workflows/tests.yml
vendored
@ -181,10 +181,11 @@ jobs:
|
|||||||
if: needs.changes.outputs.backend == 'true'
|
if: needs.changes.outputs.backend == 'true'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [changes, lint, typescript, unit_back, unit_front]
|
needs: [changes, lint, typescript, unit_back, unit_front]
|
||||||
name: '[CE] API Integration (postgres, node: ${{ matrix.node }})'
|
name: '[CE] API Integration (postgres, node: ${{ matrix.node }}, shard: ${{ matrix.shard }})'
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node: [18, 20]
|
node: [18, 20]
|
||||||
|
shard: [1/2, 2/2]
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
# Docker Hub image
|
# Docker Hub image
|
||||||
@ -214,16 +215,18 @@ jobs:
|
|||||||
- uses: ./.github/actions/run-api-tests
|
- uses: ./.github/actions/run-api-tests
|
||||||
with:
|
with:
|
||||||
dbOptions: '--dbclient=postgres --dbhost=localhost --dbport=5432 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi'
|
dbOptions: '--dbclient=postgres --dbhost=localhost --dbport=5432 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi'
|
||||||
|
jestOptions: '--shard=${{ matrix.shard }}'
|
||||||
|
|
||||||
api_ce_mysql:
|
api_ce_mysql:
|
||||||
if: needs.changes.outputs.backend == 'true'
|
if: needs.changes.outputs.backend == 'true'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [changes, lint, typescript, unit_back, unit_front]
|
needs: [changes, lint, typescript, unit_back, unit_front]
|
||||||
name: '[CE] API Integration (mysql:latest, client: ${{ matrix.db_client }}, node: ${{ matrix.node }})'
|
name: '[CE] API Integration (mysql:latest, client: ${{ matrix.db_client }}, node: ${{ matrix.node }}, shard: ${{ matrix.shard }})'
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node: [18, 20]
|
node: [18, 20]
|
||||||
db_client: ['mysql', 'mysql2']
|
db_client: ['mysql', 'mysql2']
|
||||||
|
shard: [1/2, 2/2]
|
||||||
services:
|
services:
|
||||||
mysql:
|
mysql:
|
||||||
image: bitnami/mysql:latest
|
image: bitnami/mysql:latest
|
||||||
@ -251,16 +254,18 @@ jobs:
|
|||||||
- uses: ./.github/actions/run-api-tests
|
- uses: ./.github/actions/run-api-tests
|
||||||
with:
|
with:
|
||||||
dbOptions: '--dbclient=${{ matrix.db_client }} --dbhost=localhost --dbport=3306 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi'
|
dbOptions: '--dbclient=${{ matrix.db_client }} --dbhost=localhost --dbport=3306 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi'
|
||||||
|
jestOptions: '--shard=${{ matrix.shard }}'
|
||||||
|
|
||||||
api_ce_mysql_5:
|
api_ce_mysql_5:
|
||||||
if: needs.changes.outputs.backend == 'true'
|
if: needs.changes.outputs.backend == 'true'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [changes, lint, typescript, unit_back, unit_front]
|
needs: [changes, lint, typescript, unit_back, unit_front]
|
||||||
name: '[CE] API Integration (mysql:5, client: ${{ matrix.db_client }} , node: ${{ matrix.node }})'
|
name: '[CE] API Integration (mysql:5, client: ${{ matrix.db_client }} , node: ${{ matrix.node }}, shard: ${{ matrix.shard }})'
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node: [18, 20]
|
node: [18, 20]
|
||||||
db_client: ['mysql', 'mysql2']
|
db_client: ['mysql', 'mysql2']
|
||||||
|
shard: [1/2, 2/2]
|
||||||
services:
|
services:
|
||||||
mysql:
|
mysql:
|
||||||
image: bitnami/mysql:5.7
|
image: bitnami/mysql:5.7
|
||||||
@ -287,16 +292,18 @@ jobs:
|
|||||||
- uses: ./.github/actions/run-api-tests
|
- uses: ./.github/actions/run-api-tests
|
||||||
with:
|
with:
|
||||||
dbOptions: '--dbclient=${{ matrix.db_client }} --dbhost=localhost --dbport=3306 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi'
|
dbOptions: '--dbclient=${{ matrix.db_client }} --dbhost=localhost --dbport=3306 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi'
|
||||||
|
jestOptions: '--shard=${{ matrix.shard }}'
|
||||||
|
|
||||||
api_ce_sqlite:
|
api_ce_sqlite:
|
||||||
if: needs.changes.outputs.backend == 'true'
|
if: needs.changes.outputs.backend == 'true'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [changes, lint, typescript, unit_back, unit_front]
|
needs: [changes, lint, typescript, unit_back, unit_front]
|
||||||
name: '[CE] API Integration (sqlite, client: ${{ matrix.sqlite_pkg }}, node: ${{ matrix.node }})'
|
name: '[CE] API Integration (sqlite, client: ${{ matrix.sqlite_pkg }}, node: ${{ matrix.node }}, shard: ${{ matrix.shard }})'
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node: [18, 20]
|
node: [18, 20]
|
||||||
sqlite_pkg: ['better-sqlite3', 'sqlite3']
|
sqlite_pkg: ['better-sqlite3', 'sqlite3']
|
||||||
|
shard: [1/2, 2/2]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
@ -309,18 +316,20 @@ jobs:
|
|||||||
SQLITE_PKG: ${{ matrix.sqlite_pkg }}
|
SQLITE_PKG: ${{ matrix.sqlite_pkg }}
|
||||||
with:
|
with:
|
||||||
dbOptions: '--dbclient=sqlite-legacy --dbfile=./tmp/data.db'
|
dbOptions: '--dbclient=sqlite-legacy --dbfile=./tmp/data.db'
|
||||||
|
jestOptions: '--shard=${{ matrix.shard }}'
|
||||||
|
|
||||||
# EE
|
# EE
|
||||||
api_ee_pg:
|
api_ee_pg:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [changes, lint, typescript, unit_back, unit_front]
|
needs: [changes, lint, typescript, unit_back, unit_front]
|
||||||
name: '[EE] API Integration (postgres, node: ${{ matrix.node }})'
|
name: '[EE] API Integration (postgres, node: ${{ matrix.node }}, shard: ${{ matrix.shard }})'
|
||||||
if: needs.changes.outputs.backend == 'true' && github.event.pull_request.head.repo.full_name == github.repository && !(github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]')
|
if: needs.changes.outputs.backend == 'true' && github.event.pull_request.head.repo.full_name == github.repository && !(github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]')
|
||||||
env:
|
env:
|
||||||
STRAPI_LICENSE: ${{ secrets.strapiLicense }}
|
STRAPI_LICENSE: ${{ secrets.strapiLicense }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node: [18, 20]
|
node: [18, 20]
|
||||||
|
shard: [1/2, 2/2]
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
# Docker Hub image
|
# Docker Hub image
|
||||||
@ -351,11 +360,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
dbOptions: '--dbclient=postgres --dbhost=localhost --dbport=5432 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi'
|
dbOptions: '--dbclient=postgres --dbhost=localhost --dbport=5432 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi'
|
||||||
runEE: true
|
runEE: true
|
||||||
|
jestOptions: '--shard=${{ matrix.shard }}'
|
||||||
|
|
||||||
api_ee_mysql:
|
api_ee_mysql:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [changes, lint, typescript, unit_back, unit_front]
|
needs: [changes, lint, typescript, unit_back, unit_front]
|
||||||
name: '[EE] API Integration (mysql:latest, client: ${{ matrix.db_client }}, node: ${{ matrix.node }})'
|
name: '[EE] API Integration (mysql:latest, client: ${{ matrix.db_client }}, node: ${{ matrix.node }}, shard: ${{ matrix.shard }})'
|
||||||
if: needs.changes.outputs.backend == 'true' && github.event.pull_request.head.repo.full_name == github.repository && !(github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]')
|
if: needs.changes.outputs.backend == 'true' && github.event.pull_request.head.repo.full_name == github.repository && !(github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]')
|
||||||
env:
|
env:
|
||||||
STRAPI_LICENSE: ${{ secrets.strapiLicense }}
|
STRAPI_LICENSE: ${{ secrets.strapiLicense }}
|
||||||
@ -363,6 +373,7 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
node: [18, 20]
|
node: [18, 20]
|
||||||
db_client: ['mysql', 'mysql2']
|
db_client: ['mysql', 'mysql2']
|
||||||
|
shard: [1/2, 2/2]
|
||||||
services:
|
services:
|
||||||
mysql:
|
mysql:
|
||||||
image: bitnami/mysql:latest
|
image: bitnami/mysql:latest
|
||||||
@ -391,11 +402,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
dbOptions: '--dbclient=${{ matrix.db_client }} --dbhost=localhost --dbport=3306 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi'
|
dbOptions: '--dbclient=${{ matrix.db_client }} --dbhost=localhost --dbport=3306 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi'
|
||||||
runEE: true
|
runEE: true
|
||||||
|
jestOptions: '--shard=${{ matrix.shard }}'
|
||||||
|
|
||||||
api_ee_sqlite:
|
api_ee_sqlite:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [changes, lint, typescript, unit_back, unit_front]
|
needs: [changes, lint, typescript, unit_back, unit_front]
|
||||||
name: '[EE] API Integration (sqlite, client: ${{ matrix.sqlite_pkg }}, node: ${{ matrix.node }})'
|
name: '[EE] API Integration (sqlite, client: ${{ matrix.sqlite_pkg }}, node: ${{ matrix.node }}, shard: ${{ matrix.shard }})'
|
||||||
if: needs.changes.outputs.backend == 'true' && github.event.pull_request.head.repo.full_name == github.repository && !(github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]')
|
if: needs.changes.outputs.backend == 'true' && github.event.pull_request.head.repo.full_name == github.repository && !(github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]')
|
||||||
env:
|
env:
|
||||||
STRAPI_LICENSE: ${{ secrets.strapiLicense }}
|
STRAPI_LICENSE: ${{ secrets.strapiLicense }}
|
||||||
@ -403,6 +415,7 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
node: [18, 20]
|
node: [18, 20]
|
||||||
sqlite_pkg: ['better-sqlite3', 'sqlite3']
|
sqlite_pkg: ['better-sqlite3', 'sqlite3']
|
||||||
|
shard: [1/2, 2/2]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
@ -416,3 +429,4 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
dbOptions: '--dbclient=sqlite --dbfile=./tmp/data.db'
|
dbOptions: '--dbclient=sqlite --dbfile=./tmp/data.db'
|
||||||
runEE: true
|
runEE: true
|
||||||
|
jestOptions: '--shard=${{ matrix.shard }}'
|
||||||
|
|||||||
@ -199,6 +199,8 @@ const ImageDialog = ({ handleClose }) => {
|
|||||||
const MediaLibraryDialog = components['media-library'];
|
const MediaLibraryDialog = components['media-library'];
|
||||||
|
|
||||||
const insertImages = (images) => {
|
const insertImages = (images) => {
|
||||||
|
// Image node created using select or existing selection node needs to be deleted before adding new image nodes
|
||||||
|
Transforms.removeNodes(editor);
|
||||||
images.forEach((img) => {
|
images.forEach((img) => {
|
||||||
const image = { type: 'image', image: img, children: [{ type: 'text', text: '' }] };
|
const image = { type: 'image', image: img, children: [{ type: 'text', text: '' }] };
|
||||||
Transforms.insertNodes(editor, image);
|
Transforms.insertNodes(editor, image);
|
||||||
@ -290,10 +292,7 @@ const BlocksDropdown = ({ disabled }) => {
|
|||||||
* @param {string} optionKey - key of the heading selected
|
* @param {string} optionKey - key of the heading selected
|
||||||
*/
|
*/
|
||||||
const selectOption = (optionKey) => {
|
const selectOption = (optionKey) => {
|
||||||
if (optionKey === 'image') {
|
if (['list-ordered', 'list-unordered'].includes(optionKey)) {
|
||||||
// Image node created using select or existing selection node needs to be deleted before adding new image nodes
|
|
||||||
Transforms.removeNodes(editor);
|
|
||||||
} else if (['list-ordered', 'list-unordered'].includes(optionKey)) {
|
|
||||||
// retrieve the list format
|
// retrieve the list format
|
||||||
const listFormat = blocks[optionKey].value.format;
|
const listFormat = blocks[optionKey].value.format;
|
||||||
|
|
||||||
@ -302,7 +301,7 @@ const BlocksDropdown = ({ disabled }) => {
|
|||||||
|
|
||||||
// toggle the list
|
// toggle the list
|
||||||
toggleList(editor, isActive, listFormat);
|
toggleList(editor, isActive, listFormat);
|
||||||
} else {
|
} else if (optionKey !== 'image') {
|
||||||
toggleBlock(editor, blocks[optionKey].value);
|
toggleBlock(editor, blocks[optionKey].value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,6 +506,31 @@ const LinkButton = ({ disabled }) => {
|
|||||||
return Boolean(match);
|
return Boolean(match);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isLinkDisabled = () => {
|
||||||
|
// Always disabled when the whole editor is disabled
|
||||||
|
if (disabled) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always enabled when there's no selection
|
||||||
|
if (!editor.selection) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the block node closest to the anchor and focus
|
||||||
|
const anchorNodeEntry = Editor.above(editor, {
|
||||||
|
at: editor.selection.anchor,
|
||||||
|
match: (node) => node.type !== 'text',
|
||||||
|
});
|
||||||
|
const focusNodeEntry = Editor.above(editor, {
|
||||||
|
at: editor.selection.focus,
|
||||||
|
match: (node) => node.type !== 'text',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Disabled if the anchor and focus are not in the same block
|
||||||
|
return anchorNodeEntry[0] !== focusNodeEntry[0];
|
||||||
|
};
|
||||||
|
|
||||||
const addLink = () => {
|
const addLink = () => {
|
||||||
// We insert an empty anchor, so we split the DOM to have a element we can use as reference for the popover
|
// We insert an empty anchor, so we split the DOM to have a element we can use as reference for the popover
|
||||||
insertLink(editor, { url: '' });
|
insertLink(editor, { url: '' });
|
||||||
@ -522,7 +546,7 @@ const LinkButton = ({ disabled }) => {
|
|||||||
}}
|
}}
|
||||||
isActive={isLinkActive()}
|
isActive={isLinkActive()}
|
||||||
handleClick={addLink}
|
handleClick={addLink}
|
||||||
disabled={disabled}
|
disabled={isLinkDisabled()}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -32,7 +32,10 @@ const mixedInitialValue = [
|
|||||||
{
|
{
|
||||||
type: 'heading',
|
type: 'heading',
|
||||||
level: 1,
|
level: 1,
|
||||||
children: [{ type: 'text', text: 'A heading one' }],
|
children: [
|
||||||
|
{ type: 'text', text: 'A heading one' },
|
||||||
|
{ type: 'text', text: ' with modifiers', bold: true },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'paragraph',
|
type: 'paragraph',
|
||||||
@ -433,4 +436,25 @@ describe('BlocksEditor toolbar', () => {
|
|||||||
const blocksDropdown = screen.getByRole('combobox', { name: /Select a block/i });
|
const blocksDropdown = screen.getByRole('combobox', { name: /Select a block/i });
|
||||||
expect(within(blocksDropdown).getByText(/heading 1/i)).toBeInTheDocument();
|
expect(within(blocksDropdown).getByText(/heading 1/i)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should disable the link button when multiple blocks are selected', async () => {
|
||||||
|
setup(mixedInitialValue);
|
||||||
|
|
||||||
|
// Set the selection to cover the first and second
|
||||||
|
await select({
|
||||||
|
anchor: { path: [0, 0], offset: 0 },
|
||||||
|
focus: { path: [1, 0], offset: 0 },
|
||||||
|
});
|
||||||
|
|
||||||
|
const linkButton = screen.getByLabelText(/link/i);
|
||||||
|
expect(linkButton).toBeDisabled();
|
||||||
|
|
||||||
|
// Set the selection to a range inside the same block node
|
||||||
|
await select({
|
||||||
|
anchor: { path: [0, 0], offset: 0 },
|
||||||
|
focus: { path: [0, 1], offset: 2 },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(linkButton).not.toBeDisabled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -221,7 +221,7 @@ describe('useBlocksStore', () => {
|
|||||||
const { result } = renderHook(useBlocksStore, { wrapper: Wrapper });
|
const { result } = renderHook(useBlocksStore, { wrapper: Wrapper });
|
||||||
|
|
||||||
render(
|
render(
|
||||||
result.current['heading-six'].renderElement({
|
result.current['heading-two'].renderElement({
|
||||||
children: 'Some heading',
|
children: 'Some heading',
|
||||||
element: { level: 2 },
|
element: { level: 2 },
|
||||||
attributes: {},
|
attributes: {},
|
||||||
|
|||||||
@ -37,6 +37,10 @@ import styled, { css } from 'styled-components';
|
|||||||
import { composeRefs } from '../../../utils';
|
import { composeRefs } from '../../../utils';
|
||||||
import { editLink, removeLink } from '../utils/links';
|
import { editLink, removeLink } from '../utils/links';
|
||||||
|
|
||||||
|
const StyledBaseLink = styled(BaseLink)`
|
||||||
|
text-decoration: none;
|
||||||
|
`;
|
||||||
|
|
||||||
const H1 = styled(Typography).attrs({ as: 'h1' })`
|
const H1 = styled(Typography).attrs({ as: 'h1' })`
|
||||||
font-size: ${42 / 16}rem;
|
font-size: ${42 / 16}rem;
|
||||||
line-height: ${({ theme }) => theme.lineHeights[1]};
|
line-height: ${({ theme }) => theme.lineHeights[1]};
|
||||||
@ -67,33 +71,6 @@ const H6 = styled(Typography).attrs({ as: 'h6' })`
|
|||||||
line-height: ${({ theme }) => theme.lineHeights[1]};
|
line-height: ${({ theme }) => theme.lineHeights[1]};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Heading = ({ attributes, children, element }) => {
|
|
||||||
switch (element.level) {
|
|
||||||
case 1:
|
|
||||||
return <H1 {...attributes}>{children}</H1>;
|
|
||||||
case 2:
|
|
||||||
return <H2 {...attributes}>{children}</H2>;
|
|
||||||
case 3:
|
|
||||||
return <H3 {...attributes}>{children}</H3>;
|
|
||||||
case 4:
|
|
||||||
return <H4 {...attributes}>{children}</H4>;
|
|
||||||
case 5:
|
|
||||||
return <H5 {...attributes}>{children}</H5>;
|
|
||||||
case 6:
|
|
||||||
return <H6 {...attributes}>{children}</H6>;
|
|
||||||
default: // do nothing
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Heading.propTypes = {
|
|
||||||
attributes: PropTypes.object.isRequired,
|
|
||||||
children: PropTypes.node.isRequired,
|
|
||||||
element: PropTypes.shape({
|
|
||||||
level: PropTypes.oneOf([1, 2, 3, 4, 5, 6]).isRequired,
|
|
||||||
}).isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
const CodeBlock = styled.pre.attrs({ role: 'code' })`
|
const CodeBlock = styled.pre.attrs({ role: 'code' })`
|
||||||
border-radius: ${({ theme }) => theme.borderRadius};
|
border-radius: ${({ theme }) => theme.borderRadius};
|
||||||
background-color: ${({ theme }) => theme.colors.neutral100};
|
background-color: ${({ theme }) => theme.colors.neutral100};
|
||||||
@ -113,8 +90,9 @@ const CodeBlock = styled.pre.attrs({ role: 'code' })`
|
|||||||
const Blockquote = styled.blockquote.attrs({ role: 'blockquote' })`
|
const Blockquote = styled.blockquote.attrs({ role: 'blockquote' })`
|
||||||
margin: ${({ theme }) => `${theme.spaces[4]} 0`};
|
margin: ${({ theme }) => `${theme.spaces[4]} 0`};
|
||||||
font-weight: ${({ theme }) => theme.fontWeights.regular};
|
font-weight: ${({ theme }) => theme.fontWeights.regular};
|
||||||
border-left: ${({ theme }) => `${theme.spaces[1]} solid ${theme.colors.neutral150}`};
|
border-left: ${({ theme }) => `${theme.spaces[1]} solid ${theme.colors.neutral200}`};
|
||||||
padding: ${({ theme }) => theme.spaces[2]} ${({ theme }) => theme.spaces[5]};
|
padding: ${({ theme }) => theme.spaces[2]} ${({ theme }) => theme.spaces[5]};
|
||||||
|
color: ${({ theme }) => theme.colors.neutral600};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const listStyle = css`
|
const listStyle = css`
|
||||||
@ -320,7 +298,7 @@ const Link = React.forwardRef(({ element, children, ...attributes }, forwardedRe
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<BaseLink
|
<StyledBaseLink
|
||||||
{...attributes}
|
{...attributes}
|
||||||
ref={composedRefs}
|
ref={composedRefs}
|
||||||
href={element.url}
|
href={element.url}
|
||||||
@ -328,7 +306,7 @@ const Link = React.forwardRef(({ element, children, ...attributes }, forwardedRe
|
|||||||
color="primary600"
|
color="primary600"
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</BaseLink>
|
</StyledBaseLink>
|
||||||
{popoverOpen && (
|
{popoverOpen && (
|
||||||
<Popover source={linkRef} onDismiss={handleDismiss} padding={4} contentEditable={false}>
|
<Popover source={linkRef} onDismiss={handleDismiss} padding={4} contentEditable={false}>
|
||||||
{isEditing ? (
|
{isEditing ? (
|
||||||
@ -382,9 +360,11 @@ const Link = React.forwardRef(({ element, children, ...attributes }, forwardedRe
|
|||||||
) : (
|
) : (
|
||||||
<Flex direction="column" gap={4} alignItems="start" width="400px">
|
<Flex direction="column" gap={4} alignItems="start" width="400px">
|
||||||
<Typography>{elementText}</Typography>
|
<Typography>{elementText}</Typography>
|
||||||
<BaseLink href={element.url} target="_blank" color="primary600">
|
<Typography>
|
||||||
{element.url}
|
<StyledBaseLink href={element.url} target="_blank" color="primary600">
|
||||||
</BaseLink>
|
{element.url}
|
||||||
|
</StyledBaseLink>
|
||||||
|
</Typography>
|
||||||
<Flex justifyContent="end" width="100%" gap={2}>
|
<Flex justifyContent="end" width="100%" gap={2}>
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={<Trash />}
|
icon={<Trash />}
|
||||||
@ -503,7 +483,7 @@ export function useBlocksStore() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
'heading-one': {
|
'heading-one': {
|
||||||
renderElement: (props) => <Heading {...props} />,
|
renderElement: (props) => <H1 {...props.attributes}>{props.children}</H1>,
|
||||||
icon: HeadingOne,
|
icon: HeadingOne,
|
||||||
label: {
|
label: {
|
||||||
id: 'components.Blocks.blocks.heading1',
|
id: 'components.Blocks.blocks.heading1',
|
||||||
@ -517,7 +497,7 @@ export function useBlocksStore() {
|
|||||||
isInBlocksSelector: true,
|
isInBlocksSelector: true,
|
||||||
},
|
},
|
||||||
'heading-two': {
|
'heading-two': {
|
||||||
renderElement: (props) => <Heading {...props} />,
|
renderElement: (props) => <H2 {...props.attributes}>{props.children}</H2>,
|
||||||
icon: HeadingTwo,
|
icon: HeadingTwo,
|
||||||
label: {
|
label: {
|
||||||
id: 'components.Blocks.blocks.heading2',
|
id: 'components.Blocks.blocks.heading2',
|
||||||
@ -531,7 +511,7 @@ export function useBlocksStore() {
|
|||||||
isInBlocksSelector: true,
|
isInBlocksSelector: true,
|
||||||
},
|
},
|
||||||
'heading-three': {
|
'heading-three': {
|
||||||
renderElement: (props) => <Heading {...props} />,
|
renderElement: (props) => <H3 {...props.attributes}>{props.children}</H3>,
|
||||||
icon: HeadingThree,
|
icon: HeadingThree,
|
||||||
label: {
|
label: {
|
||||||
id: 'components.Blocks.blocks.heading3',
|
id: 'components.Blocks.blocks.heading3',
|
||||||
@ -545,7 +525,7 @@ export function useBlocksStore() {
|
|||||||
isInBlocksSelector: true,
|
isInBlocksSelector: true,
|
||||||
},
|
},
|
||||||
'heading-four': {
|
'heading-four': {
|
||||||
renderElement: (props) => <Heading {...props} />,
|
renderElement: (props) => <H4 {...props.attributes}>{props.children}</H4>,
|
||||||
icon: HeadingFour,
|
icon: HeadingFour,
|
||||||
label: {
|
label: {
|
||||||
id: 'components.Blocks.blocks.heading4',
|
id: 'components.Blocks.blocks.heading4',
|
||||||
@ -559,7 +539,7 @@ export function useBlocksStore() {
|
|||||||
isInBlocksSelector: true,
|
isInBlocksSelector: true,
|
||||||
},
|
},
|
||||||
'heading-five': {
|
'heading-five': {
|
||||||
renderElement: (props) => <Heading {...props} />,
|
renderElement: (props) => <H5 {...props.attributes}>{props.children}</H5>,
|
||||||
icon: HeadingFive,
|
icon: HeadingFive,
|
||||||
label: {
|
label: {
|
||||||
id: 'components.Blocks.blocks.heading5',
|
id: 'components.Blocks.blocks.heading5',
|
||||||
@ -573,7 +553,7 @@ export function useBlocksStore() {
|
|||||||
isInBlocksSelector: true,
|
isInBlocksSelector: true,
|
||||||
},
|
},
|
||||||
'heading-six': {
|
'heading-six': {
|
||||||
renderElement: (props) => <Heading {...props} />,
|
renderElement: (props) => <H6 {...props.attributes}>{props.children}</H6>,
|
||||||
icon: HeadingSix,
|
icon: HeadingSix,
|
||||||
label: {
|
label: {
|
||||||
id: 'components.Blocks.blocks.heading6',
|
id: 'components.Blocks.blocks.heading6',
|
||||||
|
|||||||
@ -133,7 +133,7 @@ const Notification = ({
|
|||||||
},
|
},
|
||||||
onClose,
|
onClose,
|
||||||
timeout = 2500,
|
timeout = 2500,
|
||||||
title = 'success',
|
title,
|
||||||
type,
|
type,
|
||||||
}: NotificationProps) => {
|
}: NotificationProps) => {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user