Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions packages/core/lib/addons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,86 @@ export const foldableComponent = (
...props,
});

export const clickableComponent = (
props?: ComponentObject
): ComponentObject => ({
id: 'clickable',
name: (t: GetTextCallback) =>
t('core.components.clickable.name', 'Clickable'),
type: 'component',
render: () => null,
icon: 'clickable',
editable: true,
hasCustomInnerContent: true,
draggable: false,
droppable: false,
getContainers: element => [element.content as ElementObject[]],
options: [],
disallow: ['clickable'],
settings: {
title: (t: GetTextCallback) => t(
'core.components.clickable.settings.title',
'Clickable options'
),
floatingSettings: {
placement: 'right-start',
autoPlacement: {
alignment: 'start',
},
},
fields: [{
type: 'select',
key: 'action',
default: 'link',
displayable: true,
label: (t: GetTextCallback) => t(
'core.components.clickable.settings.action.title',
'Action'
),
options: [{
title: (t: GetTextCallback) => t(
'core.components.clickable.settings.action.openLink',
'Open a link'
),
value: 'link',
}, {
title: (t: GetTextCallback) => t(
'core.components.clickable.settings.action.fireEvent',
'Trigger an event'
),
value: 'event',
}],
}, {
type: 'text',
key: 'url',
default: '',
displayable: true,
label: (t: GetTextCallback) => t(
'core.components.clickable.settings.url.title',
'Link URL'
),
condition: (element: ElementObject) => element.action === 'link',
}, {
type: 'text',
key: 'event',
default: '',
displayable: true,
label: (t: GetTextCallback) => t(
'core.components.clickable.settings.event.title',
'Javascript event name'
),
condition: (element: ElementObject) => element.action === 'event',
}],
},
construct: () => ({
type: 'clickable',
action: 'link',
url: '',
content: [],
}),
...props,
});

const BORDER_STYLE_OPTIONS: ComponentSettingsFieldOptionObject[] = [{
title: (
t: GetTextCallback
Expand Down Expand Up @@ -1258,6 +1338,7 @@ export const baseComponents = (): Array<ComponentObject> => [
imageComponent(),
buttonComponent(),
foldableComponent(),
clickableComponent(),
];

export const baseSettings = (): Array<ComponentSettingsFieldObject> => [
Expand Down
16 changes: 16 additions & 0 deletions packages/react/lib/Builder/index.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,22 @@ exports[`<Builder /> should allow to add content from catalogue: Catalogue opene
Foldable
</span>
</a>
<a
class="component component-clickable oak-flex oak-items-center oak-px-2 oak-py-1 oak-gap-2 junipero"
draggable="false"
href="#"
>
<i
class="icon junipero-icons !oak-text-2xl"
>
clickable
</i>
<span
class="name"
>
Clickable
</span>
</a>
</div>
</div>
</div>
Expand Down
11 changes: 11 additions & 0 deletions packages/react/lib/addons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { type ImageFieldProps, ImageField } from './fields';
import {
Button,
Col,
Clickable,
EmptySpace,
Foldable,
Image,
Expand Down Expand Up @@ -201,6 +202,15 @@ export const foldableComponent = (
...props,
});

export const clickableComponent = (
props?: ReactComponentObject
): ReactComponentObject => ({
...coreAddons.clickableComponent(),
render: Clickable,
options: [dragOption(), backgroundColorOption()],
...props,
});

export const baseFields = (): ReactFieldObject[] => [
textField(),
textareaField(),
Expand All @@ -220,6 +230,7 @@ export const baseComponents = (): ReactComponentObject[] => [
imageComponent(),
buttonComponent(),
foldableComponent(),
clickableComponent(),
];

export const coreComponentsGroup = (): ComponentsGroupObject => ({
Expand Down
78 changes: 78 additions & 0 deletions packages/react/lib/components/Clickable/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import type { ComponentPropsWithoutRef } from 'react';
import type { ComponentObject, ElementObject } from '@oakjs/core';
import { Droppable, omit, classNames } from '@junipero/react';

import { useBuilder } from '../../hooks';
import Text from '../../Text';
import Container from '../../Container';

export interface ClickableProps extends ComponentPropsWithoutRef<'div'> {
element: ElementObject;
parent: Array<ElementObject>;
component: ComponentObject;
parentComponent: ComponentObject;
depth?: number;
}

const Clickable = ({
component,
parentComponent,
element,
parent,
className,
depth = 0,
...rest
}: ClickableProps) => {
const { builder } = useBuilder();

const onDropElement = (
position: 'before' | 'after',
sibling: ElementObject
) => {
if (parentComponent?.disallow?.includes?.(sibling.type)) {
return;
}

builder.moveElement(sibling, element, { parent, position });
};

return (
<div
{ ...omit(rest, ['builder']) }
className={classNames(
'wrapper',
depth % 2 === 0 ? 'even' : 'odd',
className,
)}
data-depth={depth}
>
<Droppable onDrop={onDropElement.bind(null, 'before')}>
<div className="drop-zone before" />
</Droppable>
<div className="sections oak-flex oak-flex-col oak-gap-4 oak-p-4">
<div className="section">
<div
className="title junipero secondary !oak-text-alternate-text-color"
>
<Text name="core.components.clickable.sectionsTitle.content">
Clickable content
</Text>
</div>
<Container
depth={depth + 1}
element={element}
content={element.content as ElementObject[]}
component={component}
/>
</div>
</div>
<Droppable onDrop={onDropElement.bind(null, 'after')}>
<div className="drop-zone after" />
</Droppable>
</div>
);
};

Clickable.displayName = 'Clickable';

export default Clickable;
5 changes: 5 additions & 0 deletions packages/react/lib/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ export {
type ButtonProps,
} from './Button';

export {
default as Clickable,
type ClickableProps,
} from './Clickable';

export {
default as Col,
type ColProps,
Expand Down
1 change: 1 addition & 0 deletions packages/react/lib/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const baseContent: ElementObject[] = [
] },
{ type: 'image', url: 'https://avatars.githubusercontent.com/u/20414672' },
{ type: 'foldable' },
{ type: 'clickable', content: [{ type: 'text', content: 'Click me' }] },
];

export const basic = () => (
Expand Down
73 changes: 73 additions & 0 deletions packages/theme/lib/Clickable.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
.oak .element.type-clickable
--background-color: var(--oak-background-color)
--inner-background-color: var(--oak-inner-background-color)

margin-top: 24px

.wrapper
&.even
& > .sections
background: var(--background-color)

&.odd
& > .sections
background: var(--inner-background-color)

.drop-zone
position: absolute
left: 0
width: 100%
z-index: 1

&::after
content: ''
width: 100%
left: 0
height: 5px
border-radius: 2px
background: var(--drop-zone-color)
opacity: 0
position: absolute
pointer-events: none

&.before
bottom: 100%
height: 24px

&::after
top: -12px

&.after
top: 100%
height: 16px

&::after
top: 6px

&.drag-enter
&::after
opacity: 1

.wrapper > .sections
border-radius: 0 10px 10px 10px

& > .options
position: absolute
bottom: 100%
left: 0
visibility: visible
transform: none
top: auto
z-index: 3

.option
&:first-child
border-radius: 5px 0 0 0

&:last-child
border-radius: 0 5px 0 0

&.dragging
.drop-zone
display: none
height: 0
1 change: 1 addition & 0 deletions packages/theme/lib/index.sass
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
@use "./Foldable"
@use "./ImageField"
@use "./Container"
@use "./Clickable"

@use "./dark"