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
24 changes: 18 additions & 6 deletions docs/ja/component/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,26 @@ Super Leopard の component パッケージでは、レポートを作成する

その他のコンポーネントは、これら2つのコンポーネントが利用しているものです。

Report Editor
-------------
### ReportEditor

### プロパティ
#### プロパティ

- `report`: (オプション) レポートの定義
- `reportId`: レポートの識別子
- `title`: レポートのタイトル
- `language`: (オプション) エディタで使用する言語
- `onSave`: レポートの定義を保存したときに呼び出されるコールバック
- `settings`: (オプション) 設定情報
- `showSaveButton`: (オプション) 保存ボタンを表示する (デフォルト: `true`)
- `additionalTools`: (オプション) 保存ボタンの前後に表示する追加ツール
- `after`: (オプション) 保存ボタンの後に表示する追加ツール
- `before`: (オプション) 保存ボタンの前に表示する追加ツール

![report editor](../images/report_editor.png)

Report
-------
### Report

### プロパティ
#### プロパティ

レポートにデータを与え、画面にプレビューを表示します。
リスト形式のレポートで複数のページに渡る場合は、`pageNumber` で指定したページが表示されます。
Expand All @@ -47,3 +49,13 @@ Report
- `pageNumber`: (オプション) 表示するページの番号
- `zoom`: (オプション) 表示するスケール(%)
- `settings`: (オプション) 設定情報

フック
-------

### useReportStates フック

レポートの状態を取得することができます。

- `report`: 現在のレポートの状態
- `dirty`: 現在のレポートのが変更されたかどうか
24 changes: 18 additions & 6 deletions packages/component/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,26 @@ The main components are as follows, although there are many components in total.

The other components are used by these two components.

Report Editor
-------------
### ReportEditor

### Properties
#### Properties

- `report`: (optional) Report definition
- `reportId`: Report identifier
- `title`: Report title
- `language`: (optional) Language to use in editor
- `onSave`: Callback to be called when report definition is saved
- `settings`: (optional) Settings information
- `showSaveButton`: (optional) Show save button (default: `true`)
- `additionalTools`: (optional) Additional tools to be shown before and/or after the save button
- `after`: (optional) Additional tools to be shown after the save button
- `before`: (optional) Additional tools to be shown before the save button

![report editor](https://github.com/sunvisor/super-leopard/raw/main/docs/images/report_editor.png)

Report
-------
### Report

### Properties
#### Properties

This function gives data to a report and displays a preview on the screen.
If the report is in list format and spans multiple pages, the page specified by `pageNumber` will be displayed.
Expand All @@ -48,6 +50,16 @@ If the report is in list format and spans multiple pages, the page specified by
- `zoom`: (optional) Scale (%) to display
- `settings`: (optional) Settings information

Hooks
------

### useReportStates

You can get the state of the report using this hook.

- `report`: The current state of the report
- `dirty`: Whether the current report has been changed or not

License
--------

Expand Down
56 changes: 56 additions & 0 deletions packages/component/src/__test_assets__/TestApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* TestApp
*
* Created by sunvisor on 2025/03/05.
* Copyright (C) Sunvisor Lab. 2025.
*/
import { Box, IconButton } from '@mui/material';
import UndoIcon from '@mui/icons-material/Undo';
import RedoIcon from '@mui/icons-material/Redo';
import { ReportEditor, ReportId, useReportStates } from '../component';
import { ReportData } from '@sunvisor/super-leopard-core';
import { billTestData } from '@sunvisor/super-leopard-test-assets';
import { useCallback } from 'react';

function HistoryTool() {
const { undo, redo, canUndo, canRedo } = useReportStates();

const handleUndo = useCallback(() => {
undo();
}, [undo]);

const handleRedo = useCallback(() => {
redo();
}, [redo]);

return (
<>
<IconButton size="small" color="inherit" onClick={handleUndo} aria-label={'undo'} disabled={!canUndo}>
<UndoIcon/>
</IconButton>
<IconButton size="small" color="inherit" onClick={handleRedo} aria-label={'redo'} disabled={!canRedo}>
<RedoIcon/>
</IconButton>
</>
)
}

export default function TestApp() {
return (
<Box>
<ReportEditor
reportId={1}
report={billTestData}
title="Bill"
onSave={function (id: ReportId, title: string, report: ReportData): void {
throw new Error(`Function not implemented. ${id}, ${title}, ${report}`);
}}
additionalTools={
{
before: <HistoryTool/>
}
}
/>
</Box>
);
}
3 changes: 3 additions & 0 deletions packages/component/src/atom/HistoryAtom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { atom } from 'jotai';
import { ReportData } from '@sunvisor/super-leopard-core';
import { RestoreReportAtom } from './ReportAtom';
import { Atom } from 'jotai';
import { ClearSelectionAtom } from './SelectionAtom';

type HistoryItem = {
report: ReportData;
Expand Down Expand Up @@ -88,6 +89,7 @@ export const UndoHistoryAtom = atom(null, (get, set) => {
if (pointer <= 0) {
return;
}
set(ClearSelectionAtom)
set(PointerAtom, pointer - 1);
set(RestoreHistoryAtom);
});
Expand All @@ -98,6 +100,7 @@ export const RedoHistoryAtom = atom(null, (get, set) => {
if (pointer > history.length - 1) {
return;
}
set(ClearSelectionAtom)
set(PointerAtom, pointer + 1);
set(RestoreHistoryAtom);
});
Expand Down
22 changes: 22 additions & 0 deletions packages/component/src/component/reportEditor/TestApp.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// noinspection JSUnusedGlobalSymbols

/**
* TestApp Story
*
* Created by sunvisor on 2025/03/05.
* Copyright (C) Sunvisor Lab. 2025.
*/
import TestApp from "../../__test_assets__/TestApp";
import { Meta, StoryObj } from '@storybook/react';

type Story = StoryObj<typeof TestApp>

const meta: Meta<typeof TestApp> = {
component: TestApp,
};

export const Normal: Story = {
args: {}
};

export default meta;
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export default function useKeyboard(listeners: Listeners, isMac: boolean = false
const { onCopy, onCut, onPaste, onRemove, onUndo, onRedo } = listeners;

const onKeyDown = useCallback((event: KeyboardEvent) => {
if (event.target instanceof HTMLElement && (["INPUT", "TEXTAREA"].includes(event.target.tagName) || event.target.isContentEditable)) {
return;
}
if (isDelete(event)) onRemove();
if (isCtrlC(event, isMac)) onCopy();
if (isCtrlV(event, isMac)) onPaste();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,30 @@
* Created by sunvisor on 2025/03/05.
* Copyright (C) Sunvisor Lab. 2025.
*/
import { useAtomValue } from 'jotai';
import { useAtomValue, useSetAtom } from 'jotai';
import { ReadReportAtom } from '../../../atom/ReportAtom';
import { ReadDirtyAtom } from '../../../atom/HistoryAtom';
import { CanRedoAtom, CanUndoAtom, ReadDirtyAtom, RedoHistoryAtom, UndoHistoryAtom } from '../../../atom/HistoryAtom';
import { useCallback } from 'react';

export default function useReportStates() {
const report = useAtomValue(ReadReportAtom);
const dirty = useAtomValue(ReadDirtyAtom);
const doUndo = useSetAtom(UndoHistoryAtom);
const doRedo = useSetAtom(RedoHistoryAtom);
const canUndo = useAtomValue(CanUndoAtom);
const canRedo = useAtomValue(CanRedoAtom);

return { report, dirty };
const undo = useCallback(() => {
if (canUndo) {
doUndo();
}
}, [doUndo, canUndo]);

const redo = useCallback(() => {
if (canRedo) {
doRedo();
}
}, [doRedo, canRedo])

return { report, dirty, undo, redo, canRedo, canUndo };
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export default function EditingLayer(props: Props) {

const onMouseDown = useCallback(
(event: React.MouseEvent<HTMLDivElement>) => {
(document.activeElement as HTMLElement).blur();
if (event.button === 0) {
handler.startRubberBand(event.clientX, event.clientY);
}
Expand Down
2 changes: 2 additions & 0 deletions packages/component/src/svg/boundingBox/BoundingBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export class BoundingBox {

const rectElement = this.drawRect(drawBox);
rectElement.on('mousedown', (event: Event) => {
(document.activeElement as HTMLElement).blur();
const e = event as MouseEvent;
if (e.button !== 0) return;
this.onHandleMouseDown(e, 'body');
Expand Down Expand Up @@ -171,6 +172,7 @@ export class BoundingBox {
classes: ['handle', type]
});
el.on('mousedown', (e: Event) => {
(document.activeElement as HTMLElement).blur();
this.onHandleMouseDown(e as MouseEvent, type);
e.preventDefault();
});
Expand Down