@adecore/ui 0.21.0 → 0.21.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/DisabledReason.js +4 -0
- package/dist/Field.js +3 -2
- package/dist/Input.js +3 -8
- package/dist/SegmentBar.js +2 -1
- package/dist/Separator.js +2 -3
- package/dist/SlidingColumn.js +1 -1
- package/dist/ZoomControls.js +4 -1
- package/dist/field-context.d.ts +5 -0
- package/dist/field-context.js +6 -0
- package/dist/file-icon.js +8 -10
- package/dist/file-tree/parts.js +8 -15
- package/dist/file-tree/use-file-tree-shift.js +4 -5
- package/dist/file-tree/use-slots.js +31 -31
- package/dist/format/datetime.js +6 -5
- package/dist/format/locale.js +6 -1
- package/dist/format/number.js +15 -18
- package/dist/menu/parts.d.ts +3 -2
- package/dist/menu/parts.js +4 -2
- package/dist/modality.js +4 -5
- package/dist/placement.d.ts +4 -0
- package/dist/placement.js +23 -0
- package/dist/popover/parts.d.ts +4 -3
- package/dist/popover/parts.js +7 -4
- package/dist/shortcut.js +9 -4
- package/dist/tabs/parts.js +3 -2
- package/dist/tree/parts.js +10 -20
- package/dist/tree/use-tree-shift.js +1 -1
- package/dist/workspace/SplitView.js +20 -14
- package/dist/workspace/TabStrip.js +19 -11
- package/dist/workspace/Workspace.js +4 -3
- package/dist/workspace/model.js +123 -122
- package/package.json +1 -1
- package/src/DisabledReason.tsx +4 -5
- package/src/Field.tsx +4 -2
- package/src/IconButton.tsx +0 -1
- package/src/Input.tsx +3 -10
- package/src/Pill.tsx +8 -1
- package/src/SegmentBar.tsx +3 -10
- package/src/Separator.tsx +2 -3
- package/src/SlidingColumn.tsx +1 -1
- package/src/ZoomControls.tsx +11 -7
- package/src/field-context.ts +7 -0
- package/src/file-icon.ts +8 -10
- package/src/file-tree/parts.tsx +17 -22
- package/src/file-tree/use-file-tree-shift.tsx +4 -7
- package/src/file-tree/use-slots.ts +31 -31
- package/src/format/datetime.ts +7 -5
- package/src/format/locale.ts +7 -7
- package/src/format/number.ts +17 -20
- package/src/menu/parts.tsx +10 -29
- package/src/modality.ts +4 -5
- package/src/placement.ts +26 -0
- package/src/popover/parts.tsx +10 -63
- package/src/settings/SettingsDialog.tsx +1 -1
- package/src/shortcut.ts +9 -4
- package/src/tabs/parts.tsx +8 -8
- package/src/tree/parts.tsx +14 -21
- package/src/tree/use-tree-shift.tsx +1 -1
- package/src/workspace/SplitView.tsx +23 -19
- package/src/workspace/TabStrip.tsx +20 -12
- package/src/workspace/Workspace.tsx +5 -3
- package/src/workspace/model.ts +141 -138
- /package/dist/{file-tree → tree}/shift.d.ts +0 -0
- /package/dist/{file-tree → tree}/shift.js +0 -0
- /package/src/{file-tree → tree}/shift.ts +0 -0
package/src/workspace/model.ts
CHANGED
|
@@ -238,6 +238,139 @@ function equalizeAxis(root: SplitNode, axis: SplitAxis, length: number, gap: num
|
|
|
238
238
|
return distribute(root, length);
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
+
type CommandOf<Type extends SplitCommand['type']> = Extract<SplitCommand, { type: Type }>;
|
|
242
|
+
|
|
243
|
+
function addPane(layout: SplitLayout, panes: SplitPane[], pane: SplitPane | undefined, command: CommandOf<'split'>): SplitLayout {
|
|
244
|
+
if (!pane || findSplitNode(layout.root, command.newPane.id) || findSplitNode(layout.root, command.splitId) || command.newPane.id === command.splitId) {
|
|
245
|
+
return layout;
|
|
246
|
+
}
|
|
247
|
+
const allViews = new Set(panes.flatMap((item) => item.views));
|
|
248
|
+
if (command.newPane.views.some((view) => allViews.has(view)) || new Set(command.newPane.views).size !== command.newPane.views.length) {
|
|
249
|
+
return layout;
|
|
250
|
+
}
|
|
251
|
+
const added = {
|
|
252
|
+
...command.newPane,
|
|
253
|
+
active: command.newPane.views.includes(command.newPane.active ?? '') ? command.newPane.active : (command.newPane.views[0] ?? null)
|
|
254
|
+
};
|
|
255
|
+
return finish(
|
|
256
|
+
{ ...layout, maximized: null },
|
|
257
|
+
replace(layout.root, pane.id, () => beside(pane, added, command.side, command.splitId)),
|
|
258
|
+
added.id
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function swapPanes(layout: SplitLayout, panes: SplitPane[], command: CommandOf<'swap'>): SplitLayout {
|
|
263
|
+
const source = panes.find((item) => item.id === command.sourceId);
|
|
264
|
+
const target = panes.find((item) => item.id === command.targetId);
|
|
265
|
+
if (!source || !target || source === target || source.views.length === 0 || (command.viewId !== undefined && !source.views.includes(command.viewId))) {
|
|
266
|
+
return layout;
|
|
267
|
+
}
|
|
268
|
+
if (command.viewId === undefined || source.views.length === 1) {
|
|
269
|
+
const exchange = (node: SplitNode): SplitNode => {
|
|
270
|
+
if (node.id === source.id) {
|
|
271
|
+
return target;
|
|
272
|
+
}
|
|
273
|
+
if (node.id === target.id) {
|
|
274
|
+
return source;
|
|
275
|
+
}
|
|
276
|
+
return node.type === 'pane' ? node : { ...node, children: node.children.map(exchange) };
|
|
277
|
+
};
|
|
278
|
+
return finish({ ...layout, maximized: null }, exchange(layout.root), source.id);
|
|
279
|
+
}
|
|
280
|
+
const moving = command.viewId;
|
|
281
|
+
const displaced = target.active;
|
|
282
|
+
const sourceNext =
|
|
283
|
+
displaced === null
|
|
284
|
+
? without(source, [moving])
|
|
285
|
+
: {
|
|
286
|
+
...source,
|
|
287
|
+
views: source.views.map((view) => (view === moving ? displaced : view)),
|
|
288
|
+
active: source.active === moving ? displaced : source.active
|
|
289
|
+
};
|
|
290
|
+
const targetNext = {
|
|
291
|
+
...target,
|
|
292
|
+
views: displaced === null ? [moving] : target.views.map((view) => (view === displaced ? moving : view)),
|
|
293
|
+
active: moving
|
|
294
|
+
};
|
|
295
|
+
const root = replace(layout.root, source.id, () => sourceNext)!;
|
|
296
|
+
return finish(
|
|
297
|
+
{ ...layout, maximized: null },
|
|
298
|
+
replace(root, target.id, () => targetNext),
|
|
299
|
+
target.id
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function moveViews(layout: SplitLayout, panes: SplitPane[], command: CommandOf<'move'>): SplitLayout {
|
|
304
|
+
const source = panes.find((item) => item.id === command.sourceId);
|
|
305
|
+
const target = panes.find((item) => item.id === command.targetId);
|
|
306
|
+
if (!source || !target || (command.viewId !== undefined && !source.views.includes(command.viewId))) {
|
|
307
|
+
return layout;
|
|
308
|
+
}
|
|
309
|
+
const moving = command.viewId === undefined ? source.views : [command.viewId];
|
|
310
|
+
if (!moving.length || (source === target && (command.viewId === undefined || (command.side !== undefined && source.views.length === 1)))) {
|
|
311
|
+
return layout;
|
|
312
|
+
}
|
|
313
|
+
let added: SplitPane | undefined;
|
|
314
|
+
if (command.side) {
|
|
315
|
+
const id = command.viewId === undefined ? source.id : command.newPaneId;
|
|
316
|
+
if (
|
|
317
|
+
!id ||
|
|
318
|
+
!command.splitId ||
|
|
319
|
+
id === command.splitId ||
|
|
320
|
+
findSplitNode(layout.root, command.splitId) ||
|
|
321
|
+
(findSplitNode(layout.root, id) && !(id === source.id && command.viewId === undefined))
|
|
322
|
+
) {
|
|
323
|
+
return layout;
|
|
324
|
+
}
|
|
325
|
+
added = { type: 'pane', id, views: moving, active: command.viewId ?? source.active };
|
|
326
|
+
}
|
|
327
|
+
const remaining = without(source, moving);
|
|
328
|
+
const root = replace(layout.root, source.id, () => (remaining.views.length || source === target ? remaining : null));
|
|
329
|
+
if (!root) {
|
|
330
|
+
return layout;
|
|
331
|
+
}
|
|
332
|
+
const next = replace(root, target.id, (node) => {
|
|
333
|
+
if (node.type !== 'pane') {
|
|
334
|
+
return node;
|
|
335
|
+
}
|
|
336
|
+
if (added && command.side && command.splitId) {
|
|
337
|
+
return beside(node, added, command.side, command.splitId);
|
|
338
|
+
}
|
|
339
|
+
const gap = Math.max(0, Math.min(target.views.length, command.index ?? target.views.length));
|
|
340
|
+
const lifted = source === target ? target.views.slice(0, gap).filter((view) => moving.includes(view)).length : 0;
|
|
341
|
+
const views = [...node.views];
|
|
342
|
+
views.splice(gap - lifted, 0, ...moving);
|
|
343
|
+
return { ...node, views, active: command.viewId ?? source.active ?? views[0] ?? null };
|
|
344
|
+
});
|
|
345
|
+
return finish({ ...layout, maximized: null }, next, added?.id ?? target.id);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function resizeBranch(layout: SplitLayout, command: CommandOf<'resize' | 'equalize'>): SplitLayout {
|
|
349
|
+
const node = findSplitNode(layout.root, command.splitId);
|
|
350
|
+
if (!node || node.type !== 'split') {
|
|
351
|
+
return layout;
|
|
352
|
+
}
|
|
353
|
+
let sizes = [...node.sizes];
|
|
354
|
+
if (command.type === 'resize') {
|
|
355
|
+
if (command.sizes.length !== node.children.length || command.sizes.some((size) => !Number.isFinite(size) || size <= 0)) {
|
|
356
|
+
return layout;
|
|
357
|
+
}
|
|
358
|
+
sizes = shares(command.sizes, node.children.length);
|
|
359
|
+
} else if (command.index === undefined) {
|
|
360
|
+
sizes = node.children.map(() => 1 / node.children.length);
|
|
361
|
+
} else {
|
|
362
|
+
const index = command.index;
|
|
363
|
+
if (index < 0 || index >= sizes.length - 1) {
|
|
364
|
+
return layout;
|
|
365
|
+
}
|
|
366
|
+
sizes[index] = sizes[index + 1] = (sizes[index]! + sizes[index + 1]!) / 2;
|
|
367
|
+
}
|
|
368
|
+
return finish(
|
|
369
|
+
layout,
|
|
370
|
+
replace(layout.root, node.id, () => ({ ...node, sizes }))
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
|
|
241
374
|
/** Invalid or stale commands are no-ops. IDs for new nodes come from the caller. */
|
|
242
375
|
export function updateSplitLayout(layout: SplitLayout, command: SplitCommand): SplitLayout {
|
|
243
376
|
const panes = splitPanes(layout.root);
|
|
@@ -289,119 +422,12 @@ export function updateSplitLayout(layout: SplitLayout, command: SplitCommand): S
|
|
|
289
422
|
pane.id
|
|
290
423
|
);
|
|
291
424
|
}
|
|
292
|
-
case 'split':
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
) {
|
|
299
|
-
return layout;
|
|
300
|
-
}
|
|
301
|
-
const allViews = new Set(panes.flatMap((item) => item.views));
|
|
302
|
-
if (command.newPane.views.some((view) => allViews.has(view)) || new Set(command.newPane.views).size !== command.newPane.views.length) {
|
|
303
|
-
return layout;
|
|
304
|
-
}
|
|
305
|
-
const added = {
|
|
306
|
-
...command.newPane,
|
|
307
|
-
active: command.newPane.views.includes(command.newPane.active ?? '') ? command.newPane.active : (command.newPane.views[0] ?? null)
|
|
308
|
-
};
|
|
309
|
-
return finish(
|
|
310
|
-
{ ...layout, maximized: null },
|
|
311
|
-
replace(layout.root, pane.id, () => beside(pane, added, command.side, command.splitId)),
|
|
312
|
-
added.id
|
|
313
|
-
);
|
|
314
|
-
}
|
|
315
|
-
case 'swap': {
|
|
316
|
-
const source = panes.find((item) => item.id === command.sourceId);
|
|
317
|
-
const target = panes.find((item) => item.id === command.targetId);
|
|
318
|
-
if (
|
|
319
|
-
!source ||
|
|
320
|
-
!target ||
|
|
321
|
-
source === target ||
|
|
322
|
-
source.views.length === 0 ||
|
|
323
|
-
(command.viewId !== undefined && !source.views.includes(command.viewId))
|
|
324
|
-
) {
|
|
325
|
-
return layout;
|
|
326
|
-
}
|
|
327
|
-
if (command.viewId === undefined || source.views.length === 1) {
|
|
328
|
-
const exchange = (node: SplitNode): SplitNode => {
|
|
329
|
-
if (node.id === source.id) {
|
|
330
|
-
return target;
|
|
331
|
-
}
|
|
332
|
-
if (node.id === target.id) {
|
|
333
|
-
return source;
|
|
334
|
-
}
|
|
335
|
-
return node.type === 'pane' ? node : { ...node, children: node.children.map(exchange) };
|
|
336
|
-
};
|
|
337
|
-
return finish({ ...layout, maximized: null }, exchange(layout.root), source.id);
|
|
338
|
-
}
|
|
339
|
-
const moving = command.viewId;
|
|
340
|
-
const displaced = target.active;
|
|
341
|
-
const sourceNext =
|
|
342
|
-
displaced === null
|
|
343
|
-
? without(source, [moving])
|
|
344
|
-
: {
|
|
345
|
-
...source,
|
|
346
|
-
views: source.views.map((view) => (view === moving ? displaced : view)),
|
|
347
|
-
active: source.active === moving ? displaced : source.active
|
|
348
|
-
};
|
|
349
|
-
const targetNext = {
|
|
350
|
-
...target,
|
|
351
|
-
views: displaced === null ? [moving] : target.views.map((view) => (view === displaced ? moving : view)),
|
|
352
|
-
active: moving
|
|
353
|
-
};
|
|
354
|
-
const root = replace(layout.root, source.id, () => sourceNext)!;
|
|
355
|
-
return finish(
|
|
356
|
-
{ ...layout, maximized: null },
|
|
357
|
-
replace(root, target.id, () => targetNext),
|
|
358
|
-
target.id
|
|
359
|
-
);
|
|
360
|
-
}
|
|
361
|
-
case 'move': {
|
|
362
|
-
const source = panes.find((item) => item.id === command.sourceId);
|
|
363
|
-
const target = panes.find((item) => item.id === command.targetId);
|
|
364
|
-
if (!source || !target || (command.viewId !== undefined && !source.views.includes(command.viewId))) {
|
|
365
|
-
return layout;
|
|
366
|
-
}
|
|
367
|
-
const moving = command.viewId === undefined ? source.views : [command.viewId];
|
|
368
|
-
if (!moving.length || (source === target && (command.viewId === undefined || (command.side !== undefined && source.views.length === 1)))) {
|
|
369
|
-
return layout;
|
|
370
|
-
}
|
|
371
|
-
let added: SplitPane | undefined;
|
|
372
|
-
if (command.side) {
|
|
373
|
-
const id = command.viewId === undefined ? source.id : command.newPaneId;
|
|
374
|
-
if (
|
|
375
|
-
!id ||
|
|
376
|
-
!command.splitId ||
|
|
377
|
-
id === command.splitId ||
|
|
378
|
-
findSplitNode(layout.root, command.splitId) ||
|
|
379
|
-
(findSplitNode(layout.root, id) && !(id === source.id && command.viewId === undefined))
|
|
380
|
-
) {
|
|
381
|
-
return layout;
|
|
382
|
-
}
|
|
383
|
-
added = { type: 'pane', id, views: moving, active: command.viewId ?? source.active };
|
|
384
|
-
}
|
|
385
|
-
const remaining = without(source, moving);
|
|
386
|
-
const root = replace(layout.root, source.id, () => (remaining.views.length || source === target ? remaining : null));
|
|
387
|
-
if (!root) {
|
|
388
|
-
return layout;
|
|
389
|
-
}
|
|
390
|
-
const next = replace(root, target.id, (node) => {
|
|
391
|
-
if (node.type !== 'pane') {
|
|
392
|
-
return node;
|
|
393
|
-
}
|
|
394
|
-
if (added && command.side && command.splitId) {
|
|
395
|
-
return beside(node, added, command.side, command.splitId);
|
|
396
|
-
}
|
|
397
|
-
const gap = Math.max(0, Math.min(target.views.length, command.index ?? target.views.length));
|
|
398
|
-
const lifted = source === target ? target.views.slice(0, gap).filter((view) => moving.includes(view)).length : 0;
|
|
399
|
-
const views = [...node.views];
|
|
400
|
-
views.splice(gap - lifted, 0, ...moving);
|
|
401
|
-
return { ...node, views, active: command.viewId ?? source.active ?? views[0] ?? null };
|
|
402
|
-
});
|
|
403
|
-
return finish({ ...layout, maximized: null }, next, added?.id ?? target.id);
|
|
404
|
-
}
|
|
425
|
+
case 'split':
|
|
426
|
+
return addPane(layout, panes, pane, command);
|
|
427
|
+
case 'swap':
|
|
428
|
+
return swapPanes(layout, panes, command);
|
|
429
|
+
case 'move':
|
|
430
|
+
return moveViews(layout, panes, command);
|
|
405
431
|
case 'equalizeAxis': {
|
|
406
432
|
const length = command.length ?? 1;
|
|
407
433
|
const gap = command.gap ?? 0;
|
|
@@ -411,30 +437,7 @@ export function updateSplitLayout(layout: SplitLayout, command: SplitCommand): S
|
|
|
411
437
|
return finish(layout, equalizeAxis(layout.root, command.axis, length, gap));
|
|
412
438
|
}
|
|
413
439
|
case 'resize':
|
|
414
|
-
case 'equalize':
|
|
415
|
-
|
|
416
|
-
if (!node || node.type !== 'split') {
|
|
417
|
-
return layout;
|
|
418
|
-
}
|
|
419
|
-
let sizes = [...node.sizes];
|
|
420
|
-
if (command.type === 'resize') {
|
|
421
|
-
if (command.sizes.length !== node.children.length || command.sizes.some((size) => !Number.isFinite(size) || size <= 0)) {
|
|
422
|
-
return layout;
|
|
423
|
-
}
|
|
424
|
-
sizes = shares(command.sizes, node.children.length);
|
|
425
|
-
} else if (command.index === undefined) {
|
|
426
|
-
sizes = node.children.map(() => 1 / node.children.length);
|
|
427
|
-
} else {
|
|
428
|
-
const index = command.index;
|
|
429
|
-
if (index < 0 || index >= sizes.length - 1) {
|
|
430
|
-
return layout;
|
|
431
|
-
}
|
|
432
|
-
sizes[index] = sizes[index + 1] = (sizes[index]! + sizes[index + 1]!) / 2;
|
|
433
|
-
}
|
|
434
|
-
return finish(
|
|
435
|
-
layout,
|
|
436
|
-
replace(layout.root, node.id, () => ({ ...node, sizes }))
|
|
437
|
-
);
|
|
438
|
-
}
|
|
440
|
+
case 'equalize':
|
|
441
|
+
return resizeBranch(layout, command);
|
|
439
442
|
}
|
|
440
443
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|