Skip to content

Commit 2ae6069

Browse files
committed
[inspector] Add cell
1 parent 6acfa0f commit 2ae6069

4 files changed

Lines changed: 69 additions & 14 deletions

File tree

src/ui-react-inspector/actions/common.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import type {Id} from '../../@types/common/index.d.ts';
33
import type {RowProps, ValueProps} from '../../@types/ui-react/index.d.ts';
44
import {useCallback, useState} from '../../common/react.ts';
55

6-
export const clonedId = (oldId: Id, exists: (newId: Id) => boolean) => {
6+
export const clonedId = (oldId: Id, has: (newId: Id) => boolean) => {
77
let newId;
88
let suffix = 1;
99
while (
10-
exists((newId = oldId + ' (copy' + (suffix > 1 ? ' ' + suffix : '') + ')'))
10+
has((newId = oldId + ' (copy' + (suffix > 1 ? ' ' + suffix : '') + ')'))
1111
) {
1212
suffix++;
1313
}
@@ -27,7 +27,7 @@ export const ConfirmableActions = <Props extends RowProps | ValueProps>({
2727
const [confirming, setConfirming] = useState<number | null>();
2828
const handleDone = useCallback(() => setConfirming(null), []);
2929
if (confirming != null) {
30-
const [, Component] = actions[confirming];
30+
const [, , Component] = actions[confirming];
3131
return (
3232
<>
3333
<Component onDone={handleDone} {...(props as any)} />
@@ -57,10 +57,12 @@ export const Clone = ({
5757
has: (id: Id) => boolean;
5858
set: (newId: Id) => void;
5959
}) => {
60-
const clone = useCallback(() => clonedId(id, has), [id, has]);
61-
const [newId, setNewId] = useState<Id>(clone);
60+
const cloneId = useCallback(() => clonedId(id, has), [id, has]);
61+
const [newId, setNewId] = useState<Id>(cloneId);
6262
const [newIdOk, setNewIdOk] = useState<boolean>(true);
63-
const [previousClone, setPreviousClone] = useState<() => Id>(() => clone);
63+
const [previousCloneId, setPreviousCloneId] = useState<() => Id>(
64+
() => cloneId,
65+
);
6466
const handleNewIdChange = (e: React.ChangeEvent<HTMLInputElement>) => {
6567
setNewId(e.target.value);
6668
setNewIdOk(!has(e.target.value));
@@ -73,9 +75,9 @@ export const Clone = ({
7375
onDone();
7476
}
7577
}, [onDone, setNewIdOk, has, set, newId]);
76-
if (clone != previousClone) {
77-
setNewId(clone);
78-
setPreviousClone(clone);
78+
if (cloneId != previousCloneId) {
79+
setNewId(cloneId);
80+
setPreviousCloneId(cloneId);
7981
}
8082
return (
8183
<>
@@ -84,7 +86,7 @@ export const Clone = ({
8486
<img
8587
onClick={handleClone}
8688
title={newIdOk ? 'Clone' : 'Id already exists'}
87-
className={newIdOk ? 'ok' : 'ok-dis'}
89+
className={newIdOk ? 'ok' : 'okDis'}
8890
/>
8991
</>
9092
);

src/ui-react-inspector/actions/row.tsx

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,55 @@
11
import type {Id} from '../../@types/index.d.ts';
22
import type {RowProps} from '../../@types/ui-react/index.d.ts';
3-
import {useCallback} from '../../common/react.ts';
3+
import {useCallback, useState} from '../../common/react.ts';
44
import {useDelRowCallback, useStoreOrStoreById} from '../../ui-react/index.ts';
5-
import {Clone, ConfirmableActions, Delete} from './common.tsx';
5+
import {Clone, clonedId, ConfirmableActions, Delete} from './common.tsx';
6+
7+
const RowAddCell = ({
8+
onDone,
9+
tableId,
10+
rowId,
11+
store: storeOrId,
12+
}: {onDone: () => void} & RowProps) => {
13+
const store = useStoreOrStoreById(storeOrId)!;
14+
const has = useCallback(
15+
(cellId: Id) => store.hasCell(tableId, rowId, cellId),
16+
[store, tableId, rowId],
17+
);
18+
const cloneId = useCallback(
19+
() => clonedId(store.getCellIds(tableId, rowId)[0], has),
20+
[store, tableId, rowId, has],
21+
);
22+
const [newId, setNewId] = useState<Id>(cloneId);
23+
const [newIdOk, setNewIdOk] = useState<boolean>(true);
24+
const [previousClone, setPreviousClone] = useState<() => Id>(() => cloneId);
25+
const handleNewIdChange = (e: React.ChangeEvent<HTMLInputElement>) => {
26+
setNewId(e.target.value);
27+
setNewIdOk(!has(e.target.value));
28+
};
29+
const handleAddCell = useCallback(() => {
30+
if (has(newId)) {
31+
setNewIdOk(false);
32+
} else {
33+
store.setCell(tableId, rowId, newId, '');
34+
onDone();
35+
}
36+
}, [onDone, setNewIdOk, has, store, newId, tableId, rowId]);
37+
if (cloneId != previousClone) {
38+
setNewId(cloneId);
39+
setPreviousClone(cloneId);
40+
}
41+
return (
42+
<>
43+
{'New Cell Id: '}
44+
<input type="text" value={newId} onChange={handleNewIdChange} />{' '}
45+
<img
46+
onClick={handleAddCell}
47+
title={newIdOk ? 'Add Cell' : 'Id already exists'}
48+
className={newIdOk ? 'ok' : 'okDis'}
49+
/>
50+
</>
51+
);
52+
};
653

754
const RowClone = ({
855
onDone,
@@ -34,6 +81,7 @@ const RowDelete = ({
3481
const RowActions = ({tableId, rowId, store}: RowProps) => (
3582
<ConfirmableActions
3683
actions={[
84+
['addCell', 'Add Cell', RowAddCell],
3785
['clone', 'Clone Row', RowClone],
3886
['delete', 'Delete Row', RowDelete],
3987
]}

src/ui-react-inspector/style.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {arrayJoin, arrayMap} from '../common/array.ts';
33
import {objNew, objToArray} from '../common/obj.ts';
44
import {UNIQUE_ID} from './common.ts';
55
import {
6+
ADD_CELL_SVG,
67
CANCEL_SVG,
78
CLONE_SVG,
89
CLOSE_SVG,
@@ -30,7 +31,7 @@ export const APP_STYLESHEET = arrayJoin(
3031
[SCROLLBAR + '-thumb']: 'background:#999;border:1px solid #111',
3132
[SCROLLBAR + '-thumb:hover']: 'background:#fff',
3233
[SCROLLBAR + '-corner']: 'background:#111',
33-
img: 'width:0.8rem;height:0.8rem;border:0;vertical-align:text-bottom;cursor:pointer',
34+
img: 'width:0.8rem;height:0.8rem;border:0;vertical-align:text-bottom;cursor:pointer;margin:0 0.125rem',
3435

3536
// Nub
3637
'>img':
@@ -104,10 +105,11 @@ export const APP_STYLESHEET = arrayJoin(
104105
'button.next': 'margin-right:0.5rem',
105106
[`th,#${UNIQUE_ID} td`]:
106107
'overflow:hidden;text-overflow:ellipsis;padding:0.25rem 0.5rem;max-width:15rem;white-space:nowrap;border-width:1px 0;border-style:solid;border-color:#777;text-align:left',
108+
'img.addCell': ADD_CELL_SVG,
107109
'img.clone': CLONE_SVG,
108110
'img.delete': DELETE_SVG,
109111
'img.ok': OK_SVG,
110-
'img.ok-dis': OK_SVG_DISABLED,
112+
'img.okDis': OK_SVG_DISABLED,
111113
'img.cancel': CANCEL_SVG,
112114

113115
'span.warn': 'margin:0.25rem;color:#d81b60',

src/ui-react-inspector/svg.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ export const EDIT_SVG = getCssSvg(
4747
export const DONE_SVG = getCssSvg(
4848
'm622-453-56-56 82-82-57-57-82 82-56-56 195-195q12-12 26.5-17.5T705-840q16 0 31 6t26 18l55 56q12 11 17.5 26t5.5 30q0 16-5.5 30.5T817-647L622-453ZM200-200h57l195-195-28-29-29-28-195 195v57ZM792-56 509-338 290-120H120v-169l219-219L56-792l57-57 736 736-57 57Zm-32-648-56-56 56 56Zm-169 56 57 57-57-57ZM424-424l-29-28 57 57-28-29Z',
4949
);
50+
export const ADD_CELL_SVG = getCssSvg(
51+
'M440-280h80v-160h160v-80H520v-160h-80v160H280v80h160v160ZM200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm0-560v560-560Z',
52+
);
5053
export const CLONE_SVG = getCssSvg(
5154
'M520-400h80v-120h120v-80H600v-120h-80v120H400v80h120v120ZM320-240q-33 0-56.5-23.5T240-320v-480q0-33 23.5-56.5T320-880h480q33 0 56.5 23.5T880-800v480q0 33-23.5 56.5T800-240H320Zm0-80h480v-480H320v480ZM160-80q-33 0-56.5-23.5T80-160v-560h80v560h560v80H160Zm160-720v480-480Z',
5255
);

0 commit comments

Comments
 (0)