mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 12:55:00 +00:00
feat(core): init organize (#7456)
This commit is contained in:
@@ -48,6 +48,7 @@ export const RenameModal = ({
|
||||
items={
|
||||
<Input
|
||||
autoFocus
|
||||
autoSelect
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
onEnter={handleRename}
|
||||
|
||||
@@ -5,6 +5,7 @@ export * from './ui/button';
|
||||
export * from './ui/checkbox';
|
||||
export * from './ui/date-picker';
|
||||
export * from './ui/divider';
|
||||
export * from './ui/dnd';
|
||||
export * from './ui/editable';
|
||||
export * from './ui/empty';
|
||||
export * from './ui/error-message';
|
||||
@@ -13,6 +14,7 @@ export * from './ui/layout';
|
||||
export * from './ui/loading';
|
||||
export * from './ui/lottie/collections-icon';
|
||||
export * from './ui/lottie/delete-icon';
|
||||
export * from './ui/lottie/folder-icon';
|
||||
export * from './ui/menu';
|
||||
export * from './ui/modal';
|
||||
export * from './ui/notification';
|
||||
|
||||
@@ -174,7 +174,10 @@ NestedDropTarget.args = {
|
||||
};
|
||||
|
||||
export const DynamicDragPreview = () => {
|
||||
type DataType = DNDData<Record<string, never>, { type: 'big' | 'small' }>;
|
||||
type DataType = DNDData<
|
||||
Record<string, never>,
|
||||
{ type: 'big' | 'small' | 'tips' }
|
||||
>;
|
||||
const { dragRef, dragging, draggingPosition, dropTarget, CustomDragPreview } =
|
||||
useDraggable<DataType>(() => ({}), []);
|
||||
const { dropTargetRef: bigDropTargetRef } = useDropTarget<DataType>(
|
||||
@@ -189,6 +192,16 @@ export const DynamicDragPreview = () => {
|
||||
}),
|
||||
[]
|
||||
);
|
||||
const {
|
||||
dropTargetRef: tipsDropTargetRef,
|
||||
draggedOver: tipsDraggedOver,
|
||||
draggedOverPosition: tipsDraggedOverPosition,
|
||||
} = useDropTarget<DataType>(
|
||||
() => ({
|
||||
data: { type: 'tips' },
|
||||
}),
|
||||
[]
|
||||
);
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -240,6 +253,30 @@ export const DynamicDragPreview = () => {
|
||||
>
|
||||
Small
|
||||
</div>
|
||||
<div
|
||||
ref={tipsDropTargetRef}
|
||||
style={{
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
border: '1px solid green',
|
||||
height: '100px',
|
||||
fontSize: '50px',
|
||||
}}
|
||||
>
|
||||
Tips
|
||||
{tipsDraggedOver && (
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
transform: `translate(${tipsDraggedOverPosition.relativeX}px, ${tipsDraggedOverPosition.relativeY}px)`,
|
||||
}}
|
||||
>
|
||||
tips
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<CustomDragPreview position="pointer-outside">
|
||||
<div
|
||||
style={{
|
||||
|
||||
@@ -43,10 +43,16 @@ export interface DraggableOptions<D extends DNDData = DNDData> {
|
||||
}>;
|
||||
canDrag?: DraggableGet<boolean>;
|
||||
disableDragPreview?: boolean;
|
||||
dragPreviewPosition?: DraggableDragPreviewPosition;
|
||||
}
|
||||
|
||||
export type DraggableDragPreviewPosition =
|
||||
| 'pointer-outside'
|
||||
| 'pointer-center'
|
||||
| 'native';
|
||||
|
||||
export type DraggableCustomDragPreviewProps = React.PropsWithChildren<{
|
||||
position?: 'pointer-outside' | 'pointer-center' | 'native';
|
||||
position?: DraggableDragPreviewPosition;
|
||||
}>;
|
||||
|
||||
export const useDraggable = <D extends DNDData = DNDData>(
|
||||
@@ -172,9 +178,11 @@ export const useDraggable = <D extends DNDData = DNDData>(
|
||||
disableNativeDragPreview({ nativeSetDragImage });
|
||||
return;
|
||||
}
|
||||
|
||||
let previewPosition: DraggableDragPreviewPosition =
|
||||
options.dragPreviewPosition ?? 'native';
|
||||
|
||||
if (enableCustomDragPreview.current) {
|
||||
let previewPosition: DraggableCustomDragPreviewProps['position'] =
|
||||
'native';
|
||||
setCustomNativeDragPreview({
|
||||
getOffset: (...args) => {
|
||||
if (previewPosition === 'pointer-center') {
|
||||
@@ -199,7 +207,7 @@ export const useDraggable = <D extends DNDData = DNDData>(
|
||||
children,
|
||||
position,
|
||||
}: DraggableCustomDragPreviewProps) => {
|
||||
previewPosition = position;
|
||||
previewPosition = position || previewPosition;
|
||||
return ReactDOM.createPortal(children, container);
|
||||
}
|
||||
);
|
||||
@@ -208,6 +216,28 @@ export const useDraggable = <D extends DNDData = DNDData>(
|
||||
},
|
||||
nativeSetDragImage,
|
||||
});
|
||||
} else if (previewPosition !== 'native') {
|
||||
setCustomNativeDragPreview({
|
||||
getOffset: (...args) => {
|
||||
if (previewPosition === 'pointer-center') {
|
||||
return centerUnderPointer(...args);
|
||||
} else if (previewPosition === 'pointer-outside') {
|
||||
return pointerOutsideOfPreview({
|
||||
x: '8px',
|
||||
y: '4px',
|
||||
})(...args);
|
||||
} else {
|
||||
return preserveOffsetOnSource({
|
||||
element: source.element,
|
||||
input: location.current.input,
|
||||
})(...args);
|
||||
}
|
||||
},
|
||||
render({ container }) {
|
||||
container.append(source.element.cloneNode(true));
|
||||
},
|
||||
nativeSetDragImage,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -100,7 +100,7 @@ export const horizontal = style({
|
||||
right: 0,
|
||||
'::before': {
|
||||
// Horizontal indicators have the terminal on the left
|
||||
left: `calc(-${terminalSize})`,
|
||||
left: `calc(-1 * ${terminalSize})`,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import type { Edge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
|
||||
import type { Instruction } from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
|
||||
@@ -20,6 +20,9 @@ type DropTargetGetFeedback<D extends DNDData> = Parameters<
|
||||
source: {
|
||||
data: D['draggable'];
|
||||
};
|
||||
} & {
|
||||
treeInstruction: Instruction | null;
|
||||
closestEdge: Edge | null;
|
||||
};
|
||||
|
||||
type DropTargetGet<T, D extends DNDData> =
|
||||
@@ -27,17 +30,60 @@ type DropTargetGet<T, D extends DNDData> =
|
||||
| ((data: DropTargetGetFeedback<D>) => T);
|
||||
|
||||
function dropTargetGet<T, D extends DNDData>(
|
||||
get: T
|
||||
get: T,
|
||||
options: DropTargetOptions<D>
|
||||
): T extends undefined
|
||||
? undefined
|
||||
: T extends DropTargetGet<infer I, D>
|
||||
? (args: DropTargetGetFeedback<D>) => I
|
||||
? (
|
||||
args: Omit<DropTargetGetFeedback<D>, 'treeInstruction' | 'closestEdge'>
|
||||
) => I
|
||||
: never {
|
||||
if (get === undefined) {
|
||||
return undefined as any;
|
||||
}
|
||||
return ((args: DropTargetGetFeedback<D>) =>
|
||||
typeof get === 'function' ? (get as any)(args) : get) as any;
|
||||
return ((
|
||||
args: Omit<DropTargetGetFeedback<D>, 'treeInstruction' | 'closestEdge'>
|
||||
) => {
|
||||
if (typeof get === 'function') {
|
||||
return (get as any)({
|
||||
...args,
|
||||
get treeInstruction() {
|
||||
return options.treeInstruction
|
||||
? extractInstruction(
|
||||
attachInstruction(
|
||||
{},
|
||||
{
|
||||
input: args.input,
|
||||
element: args.element,
|
||||
currentLevel: options.treeInstruction.currentLevel,
|
||||
indentPerLevel: options.treeInstruction.indentPerLevel,
|
||||
mode: options.treeInstruction.mode,
|
||||
block: options.treeInstruction.block,
|
||||
}
|
||||
)
|
||||
)
|
||||
: null;
|
||||
},
|
||||
get closestEdge() {
|
||||
return options.closestEdge
|
||||
? extractClosestEdge(
|
||||
attachClosestEdge(
|
||||
{},
|
||||
{
|
||||
input: args.input,
|
||||
element: args.element,
|
||||
allowedEdges: options.closestEdge.allowedEdges,
|
||||
}
|
||||
)
|
||||
)
|
||||
: null;
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return get;
|
||||
}
|
||||
}) as any;
|
||||
}
|
||||
|
||||
export type DropTargetDropEvent<D extends DNDData> = Parameters<
|
||||
@@ -52,6 +98,8 @@ export type DropTargetDragEvent<D extends DNDData> = Parameters<
|
||||
source: { data: D['draggable'] };
|
||||
};
|
||||
|
||||
export type DropTargetTreeInstruction = Instruction;
|
||||
|
||||
export interface DropTargetOptions<D extends DNDData = DNDData> {
|
||||
data?: DropTargetGet<D['dropTarget'], D>;
|
||||
canDrop?: DropTargetGet<boolean, D>;
|
||||
@@ -80,8 +128,26 @@ export const useDropTarget = <D extends DNDData = DNDData>(
|
||||
null
|
||||
);
|
||||
const [closestEdge, setClosestEdge] = useState<Edge | null>(null);
|
||||
const [dropEffect, setDropEffect] = useState<'copy' | 'link' | 'move' | null>(
|
||||
null
|
||||
);
|
||||
const [draggedOverDraggable, setDraggedOverDraggable] = useState<{
|
||||
data: D['draggable'];
|
||||
} | null>(null);
|
||||
const [draggedOverPosition, setDraggedOverPosition] = useState<{
|
||||
/**
|
||||
* relative position to the drop target element top-left corner
|
||||
*/
|
||||
relativeX: number;
|
||||
relativeY: number;
|
||||
clientX: number;
|
||||
clientY: number;
|
||||
}>({ relativeX: 0, relativeY: 0, clientX: 0, clientY: 0 });
|
||||
|
||||
const enableDraggedOver = useRef(false);
|
||||
const enableDraggedOverDraggable = useRef(false);
|
||||
const enableDraggedOverPosition = useRef(false);
|
||||
const enableDropEffect = useRef(false);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const options = useMemo(getOptions, deps);
|
||||
@@ -92,19 +158,36 @@ export const useDropTarget = <D extends DNDData = DNDData>(
|
||||
}
|
||||
return dropTargetForElements({
|
||||
element: dropTargetRef.current,
|
||||
canDrop: dropTargetGet(options.canDrop),
|
||||
getDropEffect: dropTargetGet(options.dropEffect),
|
||||
getIsSticky: dropTargetGet(options.isSticky),
|
||||
canDrop: dropTargetGet(options.canDrop, options),
|
||||
getDropEffect: dropTargetGet(options.dropEffect, options),
|
||||
getIsSticky: dropTargetGet(options.isSticky, options),
|
||||
onDrop: args => {
|
||||
if (enableDraggedOver.current) {
|
||||
setDraggedOver(false);
|
||||
}
|
||||
if (enableDraggedOverDraggable.current) {
|
||||
setDraggedOverDraggable(null);
|
||||
}
|
||||
if (enableDraggedOverPosition.current) {
|
||||
setDraggedOverPosition({
|
||||
relativeX: 0,
|
||||
relativeY: 0,
|
||||
clientX: 0,
|
||||
clientY: 0,
|
||||
});
|
||||
}
|
||||
if (options.treeInstruction) {
|
||||
setTreeInstruction(null);
|
||||
if (dropTargetRef.current) {
|
||||
delete dropTargetRef.current.dataset['treeInstruction'];
|
||||
}
|
||||
}
|
||||
if (options.closestEdge) {
|
||||
setClosestEdge(null);
|
||||
}
|
||||
if (enableDropEffect.current) {
|
||||
setDropEffect(null);
|
||||
}
|
||||
if (dropTargetRef.current) {
|
||||
delete dropTargetRef.current.dataset['draggedOver'];
|
||||
}
|
||||
@@ -120,7 +203,7 @@ export const useDropTarget = <D extends DNDData = DNDData>(
|
||||
}
|
||||
},
|
||||
getData: args => {
|
||||
const originData = dropTargetGet(options.data ?? {})(args);
|
||||
const originData = dropTargetGet(options.data ?? {}, options)(args);
|
||||
const { input, element } = args;
|
||||
const withInstruction = options.treeInstruction
|
||||
? attachInstruction(originData, {
|
||||
@@ -141,43 +224,116 @@ export const useDropTarget = <D extends DNDData = DNDData>(
|
||||
: withInstruction;
|
||||
return withClosestEdge;
|
||||
},
|
||||
onDragEnter: () => {
|
||||
if (enableDraggedOver.current) {
|
||||
setDraggedOver(true);
|
||||
}
|
||||
if (dropTargetRef.current) {
|
||||
dropTargetRef.current.dataset['draggedOver'] = 'true';
|
||||
}
|
||||
},
|
||||
onDrag: args => {
|
||||
let instruction = null;
|
||||
let closestEdge = null;
|
||||
if (options.treeInstruction) {
|
||||
instruction = extractInstruction(args.self.data);
|
||||
setTreeInstruction(instruction);
|
||||
if (
|
||||
args.location.current.dropTargets[0]?.element ===
|
||||
dropTargetRef.current
|
||||
) {
|
||||
if (enableDraggedOverDraggable.current) {
|
||||
setDraggedOverDraggable({ data: args.source.data });
|
||||
}
|
||||
let instruction = null;
|
||||
let closestEdge = null;
|
||||
if (options.treeInstruction) {
|
||||
instruction = extractInstruction(args.self.data);
|
||||
setTreeInstruction(instruction);
|
||||
if (dropTargetRef.current) {
|
||||
dropTargetRef.current.dataset['treeInstruction'] =
|
||||
instruction?.type;
|
||||
}
|
||||
}
|
||||
if (options.closestEdge) {
|
||||
closestEdge = extractClosestEdge(args.self.data);
|
||||
setClosestEdge(closestEdge);
|
||||
}
|
||||
if (enableDropEffect.current) {
|
||||
setDropEffect(args.self.dropEffect);
|
||||
}
|
||||
if (enableDraggedOverPosition.current) {
|
||||
const rect = args.self.element.getBoundingClientRect();
|
||||
const { clientX, clientY } = args.location.current.input;
|
||||
setDraggedOverPosition({
|
||||
relativeX: clientX - rect.x,
|
||||
relativeY: clientY - rect.y,
|
||||
clientX: clientX,
|
||||
clientY: clientY,
|
||||
});
|
||||
}
|
||||
options.onDrag?.({
|
||||
...args,
|
||||
treeInstruction: instruction,
|
||||
closestEdge,
|
||||
} as DropTargetDropEvent<D>);
|
||||
}
|
||||
if (options.closestEdge) {
|
||||
closestEdge = extractClosestEdge(args.self.data);
|
||||
setClosestEdge(closestEdge);
|
||||
}
|
||||
options.onDrag?.({
|
||||
...args,
|
||||
treeInstruction: instruction,
|
||||
closestEdge,
|
||||
} as DropTargetDropEvent<D>);
|
||||
},
|
||||
onDragLeave: () => {
|
||||
if (enableDraggedOver.current) {
|
||||
setDraggedOver(false);
|
||||
}
|
||||
if (options.treeInstruction) {
|
||||
setTreeInstruction(null);
|
||||
}
|
||||
if (options.closestEdge) {
|
||||
setClosestEdge(null);
|
||||
}
|
||||
if (dropTargetRef.current) {
|
||||
delete dropTargetRef.current.dataset['draggedOver'];
|
||||
onDropTargetChange: args => {
|
||||
if (
|
||||
args.location.current.dropTargets[0]?.element ===
|
||||
dropTargetRef.current
|
||||
) {
|
||||
if (enableDraggedOver.current) {
|
||||
setDraggedOver(true);
|
||||
}
|
||||
if (options.treeInstruction) {
|
||||
const instruction = extractInstruction(args.self.data);
|
||||
setTreeInstruction(instruction);
|
||||
if (dropTargetRef.current) {
|
||||
dropTargetRef.current.dataset['treeInstruction'] =
|
||||
instruction?.type;
|
||||
}
|
||||
}
|
||||
if (options.closestEdge) {
|
||||
const closestEdge = extractClosestEdge(args.self.data);
|
||||
setClosestEdge(closestEdge);
|
||||
}
|
||||
if (enableDropEffect.current) {
|
||||
setDropEffect(args.self.dropEffect);
|
||||
}
|
||||
if (enableDraggedOverDraggable.current) {
|
||||
setDraggedOverDraggable({ data: args.source.data });
|
||||
}
|
||||
if (enableDraggedOverPosition.current) {
|
||||
const rect = args.self.element.getBoundingClientRect();
|
||||
setDraggedOverPosition({
|
||||
relativeX: args.location.current.input.clientX - rect.x,
|
||||
relativeY: args.location.current.input.clientY - rect.y,
|
||||
clientX: args.location.current.input.clientX,
|
||||
clientY: args.location.current.input.clientY,
|
||||
});
|
||||
}
|
||||
if (dropTargetRef.current) {
|
||||
dropTargetRef.current.dataset['draggedOver'] = 'true';
|
||||
}
|
||||
} else {
|
||||
if (enableDraggedOver.current) {
|
||||
setDraggedOver(false);
|
||||
}
|
||||
if (enableDraggedOverDraggable.current) {
|
||||
setDraggedOverDraggable(null);
|
||||
}
|
||||
if (options.treeInstruction) {
|
||||
setTreeInstruction(null);
|
||||
if (dropTargetRef.current) {
|
||||
delete dropTargetRef.current.dataset['treeInstruction'];
|
||||
}
|
||||
}
|
||||
if (enableDropEffect.current) {
|
||||
setDropEffect(args.self.dropEffect);
|
||||
}
|
||||
if (enableDraggedOverPosition.current) {
|
||||
setDraggedOverPosition({
|
||||
relativeX: 0,
|
||||
relativeY: 0,
|
||||
clientX: 0,
|
||||
clientY: 0,
|
||||
});
|
||||
}
|
||||
if (options.closestEdge) {
|
||||
setClosestEdge(null);
|
||||
}
|
||||
if (dropTargetRef.current) {
|
||||
delete dropTargetRef.current.dataset['draggedOver'];
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -189,6 +345,18 @@ export const useDropTarget = <D extends DNDData = DNDData>(
|
||||
enableDraggedOver.current = true;
|
||||
return draggedOver;
|
||||
},
|
||||
get draggedOverDraggable() {
|
||||
enableDraggedOverDraggable.current = true;
|
||||
return draggedOverDraggable;
|
||||
},
|
||||
get draggedOverPosition() {
|
||||
enableDraggedOverPosition.current = true;
|
||||
return draggedOverPosition;
|
||||
},
|
||||
get dropEffect() {
|
||||
enableDropEffect.current = true;
|
||||
return dropEffect;
|
||||
},
|
||||
treeInstruction,
|
||||
closestEdge,
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@ import type {
|
||||
KeyboardEventHandler,
|
||||
ReactNode,
|
||||
} from 'react';
|
||||
import { forwardRef, useCallback } from 'react';
|
||||
import { forwardRef, useCallback, useLayoutEffect, useRef } from 'react';
|
||||
|
||||
import { input, inputWrapper } from './style.css';
|
||||
|
||||
@@ -18,6 +18,7 @@ export type InputProps = {
|
||||
onChange?: (value: string) => void;
|
||||
onBlur?: FocusEventHandler<HTMLInputElement>;
|
||||
onKeyDown?: KeyboardEventHandler<HTMLInputElement>;
|
||||
autoSelect?: boolean;
|
||||
noBorder?: boolean;
|
||||
status?: 'error' | 'success' | 'warning' | 'default';
|
||||
size?: 'default' | 'large' | 'extraLarge';
|
||||
@@ -43,23 +44,20 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
|
||||
onEnter,
|
||||
onKeyDown,
|
||||
autoFocus,
|
||||
autoSelect,
|
||||
...otherProps
|
||||
}: InputProps,
|
||||
upstreamRef: ForwardedRef<HTMLInputElement>
|
||||
) {
|
||||
const handleAutoFocus = useCallback(
|
||||
(ref: HTMLInputElement | null) => {
|
||||
if (ref) {
|
||||
window.setTimeout(() => ref.focus(), 0);
|
||||
if (typeof upstreamRef === 'function') {
|
||||
upstreamRef(ref);
|
||||
} else if (upstreamRef) {
|
||||
upstreamRef.current = ref;
|
||||
}
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
useLayoutEffect(() => {
|
||||
if (inputRef.current && (autoFocus || autoSelect)) {
|
||||
inputRef.current?.focus();
|
||||
if (autoSelect) {
|
||||
inputRef.current?.select();
|
||||
}
|
||||
},
|
||||
[upstreamRef]
|
||||
);
|
||||
}
|
||||
}, [autoFocus, autoSelect, upstreamRef]);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -86,7 +84,16 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
|
||||
large: size === 'large',
|
||||
'extra-large': size === 'extraLarge',
|
||||
})}
|
||||
ref={autoFocus ? handleAutoFocus : upstreamRef}
|
||||
ref={ref => {
|
||||
inputRef.current = ref;
|
||||
if (upstreamRef) {
|
||||
if (typeof upstreamRef === 'function') {
|
||||
upstreamRef(ref);
|
||||
} else {
|
||||
upstreamRef.current = ref;
|
||||
}
|
||||
}
|
||||
}}
|
||||
disabled={disabled}
|
||||
style={inputStyle}
|
||||
onChange={useCallback(
|
||||
|
||||
421
packages/frontend/component/src/ui/lottie/folder-icon.json
Normal file
421
packages/frontend/component/src/ui/lottie/folder-icon.json
Normal file
@@ -0,0 +1,421 @@
|
||||
{
|
||||
"v": "5.12.1",
|
||||
"fr": 60,
|
||||
"ip": 0,
|
||||
"op": 89,
|
||||
"w": 240,
|
||||
"h": 240,
|
||||
"nm": "folder",
|
||||
"ddd": 0,
|
||||
"assets": [],
|
||||
"layers": [
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 1,
|
||||
"ty": 4,
|
||||
"nm": "“图层 2”轮廓 3",
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": { "a": 0, "k": 100, "ix": 11 },
|
||||
"r": { "a": 0, "k": 0, "ix": 10 },
|
||||
"p": { "a": 0, "k": [120, 120, 0], "ix": 2, "l": 2 },
|
||||
"a": { "a": 0, "k": [12, 12, 0], "ix": 1, "l": 2 },
|
||||
"s": { "a": 0, "k": [1000, 1000, 100], "ix": 6, "l": 2 }
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"it": [
|
||||
{
|
||||
"ind": 0,
|
||||
"ty": "sh",
|
||||
"ix": 1,
|
||||
"ks": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"i": { "x": 0.833, "y": 0.833 },
|
||||
"o": { "x": 0.167, "y": 0.167 },
|
||||
"t": 0,
|
||||
"s": [
|
||||
{
|
||||
"i": [
|
||||
[0, 0],
|
||||
[-1.105, 0],
|
||||
[0, 0],
|
||||
[0, 0],
|
||||
[0, 0],
|
||||
[-0.366, -0.46],
|
||||
[0, 0],
|
||||
[1.105, 0],
|
||||
[0, 0],
|
||||
[0, 1.105]
|
||||
],
|
||||
"o": [
|
||||
[0, -1.105],
|
||||
[0, 0],
|
||||
[0.53, 0],
|
||||
[0, 0],
|
||||
[0.634, 0],
|
||||
[0.272, 0.342],
|
||||
[0, 1.105],
|
||||
[0, 0],
|
||||
[-1.105, 0],
|
||||
[0, 0]
|
||||
],
|
||||
"v": [
|
||||
[-9, -5.25],
|
||||
[-7, -7.25],
|
||||
[-2.328, -7.25],
|
||||
[0.5, -5.25],
|
||||
[7, -5.25],
|
||||
[8.565, -4.495],
|
||||
[9, 5.25],
|
||||
[7, 7.25],
|
||||
[-7, 7.25],
|
||||
[-9, 5.25]
|
||||
],
|
||||
"c": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 5,
|
||||
"s": [
|
||||
{
|
||||
"i": [
|
||||
[0, 0],
|
||||
[-1.105, 0],
|
||||
[0, 0],
|
||||
[0, 0],
|
||||
[0, 0],
|
||||
[-0.002, -0.756],
|
||||
[0, 0],
|
||||
[1.105, 0],
|
||||
[0, 0],
|
||||
[0, 1.105]
|
||||
],
|
||||
"o": [
|
||||
[0.225, -0.675],
|
||||
[0, 0],
|
||||
[0.53, 0],
|
||||
[0, 0],
|
||||
[2.525, -0.05],
|
||||
[-0.002, 0.982],
|
||||
[-0.375, 1.05],
|
||||
[0, 0],
|
||||
[-1.105, 0],
|
||||
[0, 0]
|
||||
],
|
||||
"v": [
|
||||
[-7.5, 0.35],
|
||||
[-5.5, -1.65],
|
||||
[-0.828, -1.65],
|
||||
[2, -1.637],
|
||||
[7.825, -1.612],
|
||||
[10.577, 0.344],
|
||||
[9.075, 5.25],
|
||||
[7.075, 7.25],
|
||||
[-7, 7.25],
|
||||
[-9, 5.25]
|
||||
],
|
||||
"c": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"nm": "路径 1",
|
||||
"mn": "ADBE Vector Shape - Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "st",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [0.466666666667, 0.458823529412, 0.490196078431, 1],
|
||||
"ix": 3
|
||||
},
|
||||
"o": { "a": 0, "k": 100, "ix": 4 },
|
||||
"w": { "a": 0, "k": 1.5, "ix": 5 },
|
||||
"lc": 1,
|
||||
"lj": 2,
|
||||
"bm": 0,
|
||||
"nm": "描边 1",
|
||||
"mn": "ADBE Vector Graphic - Stroke",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"p": { "a": 0, "k": [12, 11.75], "ix": 2 },
|
||||
"a": { "a": 0, "k": [0, 0], "ix": 1 },
|
||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
||||
"nm": "变换"
|
||||
}
|
||||
],
|
||||
"nm": "组 1",
|
||||
"np": 2,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": 1,
|
||||
"op": 18060,
|
||||
"st": 0,
|
||||
"ct": 1,
|
||||
"bm": 0
|
||||
},
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 2,
|
||||
"ty": 4,
|
||||
"nm": "形状图层 1",
|
||||
"td": 1,
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": { "a": 0, "k": 100, "ix": 11 },
|
||||
"r": { "a": 0, "k": 0, "ix": 10 },
|
||||
"p": { "a": 0, "k": [120, 120, 0], "ix": 2, "l": 2 },
|
||||
"a": { "a": 0, "k": [0, 0, 0], "ix": 1, "l": 2 },
|
||||
"s": { "a": 0, "k": [100, 100, 100], "ix": 6, "l": 2 }
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"it": [
|
||||
{
|
||||
"ind": 0,
|
||||
"ty": "sh",
|
||||
"ix": 1,
|
||||
"ks": {
|
||||
"a": 1,
|
||||
"k": [
|
||||
{
|
||||
"i": { "x": 0.833, "y": 0.833 },
|
||||
"o": { "x": 0.167, "y": 0.167 },
|
||||
"t": 0,
|
||||
"s": [
|
||||
{
|
||||
"i": [
|
||||
[0, 0],
|
||||
[0, 0],
|
||||
[0, 0],
|
||||
[0, 0]
|
||||
],
|
||||
"o": [
|
||||
[0, 0],
|
||||
[0, 0],
|
||||
[0, 0],
|
||||
[0, 0]
|
||||
],
|
||||
"v": [
|
||||
[77.675, -57.65],
|
||||
[77.675, 39.75],
|
||||
[-74.425, 39.801],
|
||||
[-74.425, -57.6]
|
||||
],
|
||||
"c": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"t": 5,
|
||||
"s": [
|
||||
{
|
||||
"i": [
|
||||
[0, 0],
|
||||
[0, 0],
|
||||
[0, 0],
|
||||
[0, 0]
|
||||
],
|
||||
"o": [
|
||||
[0, 0],
|
||||
[0, 0],
|
||||
[0, 0],
|
||||
[0, 0]
|
||||
],
|
||||
"v": [
|
||||
[107.675, -32.825],
|
||||
[84.175, 45.15],
|
||||
[-80.425, 45.075],
|
||||
[-80.425, -34.825]
|
||||
],
|
||||
"c": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"ix": 2
|
||||
},
|
||||
"nm": "路径 1",
|
||||
"mn": "ADBE Vector Shape - Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "fl",
|
||||
"c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 },
|
||||
"o": { "a": 0, "k": 100, "ix": 5 },
|
||||
"r": 1,
|
||||
"bm": 0,
|
||||
"nm": "填充 1",
|
||||
"mn": "ADBE Vector Graphic - Fill",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"p": { "a": 0, "k": [-1.575, 18.575], "ix": 2 },
|
||||
"a": { "a": 0, "k": [0, 0], "ix": 1 },
|
||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
||||
"nm": "变换"
|
||||
}
|
||||
],
|
||||
"nm": "矩形 1",
|
||||
"np": 3,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 18060,
|
||||
"st": 0,
|
||||
"ct": 1,
|
||||
"bm": 0
|
||||
},
|
||||
{
|
||||
"ddd": 0,
|
||||
"ind": 3,
|
||||
"ty": 4,
|
||||
"nm": "“图层 2”轮廓",
|
||||
"tt": 2,
|
||||
"tp": 2,
|
||||
"sr": 1,
|
||||
"ks": {
|
||||
"o": { "a": 0, "k": 100, "ix": 11 },
|
||||
"r": { "a": 0, "k": 0, "ix": 10 },
|
||||
"p": { "a": 0, "k": [120, 120, 0], "ix": 2, "l": 2 },
|
||||
"a": { "a": 0, "k": [12, 12, 0], "ix": 1, "l": 2 },
|
||||
"s": { "a": 0, "k": [1000, 1000, 100], "ix": 6, "l": 2 }
|
||||
},
|
||||
"ao": 0,
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "gr",
|
||||
"it": [
|
||||
{
|
||||
"ind": 0,
|
||||
"ty": "sh",
|
||||
"ix": 1,
|
||||
"ks": {
|
||||
"a": 0,
|
||||
"k": {
|
||||
"i": [
|
||||
[0, 0],
|
||||
[-1.105, 0],
|
||||
[0, 0],
|
||||
[-0.375, -0.375],
|
||||
[0, 0],
|
||||
[0, 0],
|
||||
[0, -1.105],
|
||||
[0, 0],
|
||||
[1.105, 0],
|
||||
[0, 0],
|
||||
[0, 1.105]
|
||||
],
|
||||
"o": [
|
||||
[0, -1.105],
|
||||
[0, 0],
|
||||
[0.53, 0],
|
||||
[0, 0],
|
||||
[0, 0],
|
||||
[1.105, 0],
|
||||
[0, 0],
|
||||
[0, 1.105],
|
||||
[0, 0],
|
||||
[-1.105, 0],
|
||||
[0, 0]
|
||||
],
|
||||
"v": [
|
||||
[-9, -5.25],
|
||||
[-7, -7.25],
|
||||
[-2.328, -7.25],
|
||||
[-0.914, -6.664],
|
||||
[0.5, -5.25],
|
||||
[7, -5.25],
|
||||
[9, -3.25],
|
||||
[9, 5.25],
|
||||
[7, 7.25],
|
||||
[-7, 7.25],
|
||||
[-9, 5.25]
|
||||
],
|
||||
"c": true
|
||||
},
|
||||
"ix": 2
|
||||
},
|
||||
"nm": "路径 1",
|
||||
"mn": "ADBE Vector Shape - Group",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "st",
|
||||
"c": {
|
||||
"a": 0,
|
||||
"k": [0.466666666667, 0.458823529412, 0.490196078431, 1],
|
||||
"ix": 3
|
||||
},
|
||||
"o": { "a": 0, "k": 100, "ix": 4 },
|
||||
"w": { "a": 0, "k": 1.5, "ix": 5 },
|
||||
"lc": 1,
|
||||
"lj": 2,
|
||||
"bm": 0,
|
||||
"nm": "描边 1",
|
||||
"mn": "ADBE Vector Graphic - Stroke",
|
||||
"hd": false
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"p": { "a": 0, "k": [12, 11.75], "ix": 2 },
|
||||
"a": { "a": 0, "k": [0, 0], "ix": 1 },
|
||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
||||
"nm": "变换"
|
||||
}
|
||||
],
|
||||
"nm": "组 1",
|
||||
"np": 2,
|
||||
"cix": 2,
|
||||
"bm": 0,
|
||||
"ix": 1,
|
||||
"mn": "ADBE Vector Group",
|
||||
"hd": false
|
||||
}
|
||||
],
|
||||
"ip": 0,
|
||||
"op": 18060,
|
||||
"st": 0,
|
||||
"ct": 1,
|
||||
"bm": 0
|
||||
}
|
||||
],
|
||||
"markers": [],
|
||||
"props": {}
|
||||
}
|
||||
39
packages/frontend/component/src/ui/lottie/folder-icon.tsx
Normal file
39
packages/frontend/component/src/ui/lottie/folder-icon.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import clsx from 'clsx';
|
||||
import type { LottieRef } from 'lottie-react';
|
||||
import Lottie from 'lottie-react';
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
import animationData from './folder-icon.json';
|
||||
import * as styles from './styles.css';
|
||||
|
||||
export interface FolderIconProps {
|
||||
closed: boolean; // eg, when folder icon is a "dragged over" state
|
||||
className?: string;
|
||||
}
|
||||
|
||||
// animated folder icon that has two states: closed and opened
|
||||
export const AnimatedFolderIcon = ({ closed, className }: FolderIconProps) => {
|
||||
const lottieRef: LottieRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (lottieRef.current) {
|
||||
const lottie = lottieRef.current;
|
||||
if (closed) {
|
||||
lottie.setDirection(1);
|
||||
} else {
|
||||
lottie.setDirection(-1);
|
||||
}
|
||||
lottie.play();
|
||||
}
|
||||
}, [closed]);
|
||||
|
||||
return (
|
||||
<Lottie
|
||||
className={clsx(styles.root, className)}
|
||||
autoPlay={false}
|
||||
loop={false}
|
||||
lottieRef={lottieRef}
|
||||
animationData={animationData}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -62,11 +62,19 @@ export const ConfirmModal = ({
|
||||
})}
|
||||
>
|
||||
<DialogTrigger asChild>
|
||||
<Button onClick={onCancel} {...cancelButtonOptions}>
|
||||
<Button
|
||||
onClick={onCancel}
|
||||
data-testid="confirm-modal-cancel"
|
||||
{...cancelButtonOptions}
|
||||
>
|
||||
{cancelText}
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<Button onClick={onConfirmClick} {...confirmButtonOptions}>
|
||||
<Button
|
||||
onClick={onConfirmClick}
|
||||
data-testid="confirm-modal-confirm"
|
||||
{...confirmButtonOptions}
|
||||
>
|
||||
{confirmText}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user