@nvidia-elements/core 2.23.5 → 2.23.6
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/CHANGELOG.md +6 -0
- package/dist/accordion/accordion2.js +4 -4
- package/dist/alert/alert-group2.js +1 -1
- package/dist/alert/alert2.js +1 -1
- package/dist/avatar/avatar-group2.js +1 -1
- package/dist/avatar/avatar2.js +1 -1
- package/dist/badge/badge2.js +1 -1
- package/dist/breadcrumb/breadcrumb2.js +1 -1
- package/dist/bundles/index.js +7 -7
- package/dist/button/button2.js +1 -1
- package/dist/button-group/button-group2.js +1 -1
- package/dist/card/card2.js +4 -4
- package/dist/chat-message/chat-message2.js +1 -1
- package/dist/checkbox/checkbox-group2.js +1 -1
- package/dist/checkbox/checkbox2.js +1 -1
- package/dist/color/color2.js +1 -1
- package/dist/combobox/combobox2.js +1 -1
- package/dist/copy-button/copy-button2.js +1 -1
- package/dist/custom-elements.json +1000 -229
- package/dist/date/date2.js +1 -1
- package/dist/datetime/datetime2.js +1 -1
- package/dist/dialog/dialog-footer2.js +1 -1
- package/dist/dialog/dialog-header2.js +1 -1
- package/dist/dialog/dialog2.js +1 -1
- package/dist/divider/divider2.js +1 -1
- package/dist/dot/dot2.js +1 -1
- package/dist/drag-handle/drag-handle2.js +1 -1
- package/dist/drawer/drawer-content2.js +1 -1
- package/dist/drawer/drawer-footer2.js +1 -1
- package/dist/drawer/drawer-header2.js +1 -1
- package/dist/drawer/drawer2.js +1 -1
- package/dist/dropdown/dropdown-footer2.js +1 -1
- package/dist/dropdown/dropdown-header2.js +1 -1
- package/dist/dropdown/dropdown2.js +1 -1
- package/dist/dropdown-group/dropdown-group.js +1 -1
- package/dist/dropzone/dropzone2.js +1 -1
- package/dist/file/file2.js +1 -1
- package/dist/format-bytes/format-bytes2.js +1 -1
- package/dist/format-datetime/format-datetime2.js +1 -1
- package/dist/format-number/format-number2.js +1 -1
- package/dist/format-relative-time/format-relative-time2.js +1 -1
- package/dist/format-truncate/format-truncate2.js +1 -1
- package/dist/forms/control/control2.js +1 -1
- package/dist/forms/control-group/control-group2.js +1 -1
- package/dist/forms/control-message/control-message2.js +1 -1
- package/dist/gauge/gauge2.js +1 -1
- package/dist/ghost/ghost2.js +1 -1
- package/dist/grid/cell/cell2.js +1 -1
- package/dist/grid/column/column2.js +1 -1
- package/dist/grid/footer/footer2.js +1 -1
- package/dist/grid/grid2.js +1 -1
- package/dist/grid/header/header2.js +1 -1
- package/dist/grid/placeholder/placeholder2.js +1 -1
- package/dist/grid/row/row2.js +1 -1
- package/dist/icon/icon2.js +1 -1
- package/dist/icon-button/icon-button2.js +1 -1
- package/dist/iframe/iframe2.js +1 -1
- package/dist/index.js +1 -1
- package/dist/input/input-group2.js +1 -1
- package/dist/input/input2.js +1 -1
- package/dist/joystick/joystick2.js +1 -1
- package/dist/logo/logo2.js +1 -1
- package/dist/menu/menu-group2.js +1 -1
- package/dist/menu/menu-item2.js +1 -1
- package/dist/menu/menu2.js +1 -1
- package/dist/month/month2.js +1 -1
- package/dist/notification/notification-group2.js +1 -1
- package/dist/notification/notification2.js +1 -1
- package/dist/page/page-panel/page-panel-content2.js +1 -1
- package/dist/page/page-panel/page-panel-footer2.js +1 -1
- package/dist/page/page-panel/page-panel-header2.js +1 -1
- package/dist/page/page-panel/page-panel2.js +1 -1
- package/dist/page/page2.js +1 -1
- package/dist/page-header/page-header2.js +1 -1
- package/dist/page-loader/page-loader2.js +1 -1
- package/dist/pagination/pagination2.js +1 -1
- package/dist/panel/panel2.js +4 -4
- package/dist/password/password2.js +1 -1
- package/dist/preferences-input/preferences-input2.js +1 -1
- package/dist/progress-bar/progress-bar2.js +1 -1
- package/dist/progress-dot/progress-dot2.js +1 -1
- package/dist/progress-ring/progress-ring2.js +1 -1
- package/dist/progressive-filter-chip/progressive-filter-chip2.js +1 -1
- package/dist/pulse/pulse2.js +1 -1
- package/dist/radio/radio-group2.js +1 -1
- package/dist/radio/radio2.js +1 -1
- package/dist/range/range2.js +1 -1
- package/dist/resize-handle/resize-handle2.js +1 -1
- package/dist/search/search2.js +1 -1
- package/dist/select/select2.js +1 -1
- package/dist/skeleton/skeleton2.js +1 -1
- package/dist/sort-button/sort-button2.js +1 -1
- package/dist/sparkline/sparkline2.js +1 -1
- package/dist/star-rating/star-rating2.js +1 -1
- package/dist/steps/steps2.js +2 -2
- package/dist/switch/switch-group2.js +1 -1
- package/dist/switch/switch2.js +1 -1
- package/dist/tabs/tabs-group2.js +1 -1
- package/dist/tabs/tabs-item-group2.js +1 -1
- package/dist/tabs/tabs2.js +2 -2
- package/dist/tag/tag2.js +1 -1
- package/dist/textarea/textarea2.js +1 -1
- package/dist/time/time2.js +1 -1
- package/dist/toast/toast2.js +1 -1
- package/dist/toggletip/toggletip-footer2.js +1 -1
- package/dist/toggletip/toggletip-header2.js +1 -1
- package/dist/toggletip/toggletip2.js +1 -1
- package/dist/toolbar/toolbar2.js +1 -1
- package/dist/tooltip/tooltip2.js +1 -1
- package/dist/tree/tree-node2.js +1 -1
- package/dist/tree/tree2.js +1 -1
- package/dist/week/week2.js +1 -1
- package/dist/workspace/controllers/workspace-composition.controller.d.ts +4 -1
- package/dist/workspace/controllers/workspace-composition.controller.js +69 -39
- package/dist/workspace/controllers/workspace-composition.controller.js.map +1 -1
- package/dist/workspace/controllers/workspace-rearrange.controller.js +27 -27
- package/dist/workspace/controllers/workspace-rearrange.controller.js.map +1 -1
- package/dist/workspace/controllers/workspace-restoration.controller.js +2 -2
- package/dist/workspace/controllers/workspace-restoration.controller.js.map +1 -1
- package/dist/workspace/panel/panel2.js +2 -2
- package/dist/workspace/panel/panel2.js.map +1 -1
- package/dist/workspace/panel-content/panel-content2.js +1 -1
- package/dist/workspace/panel-footer/panel-footer2.js +1 -1
- package/dist/workspace/panel-header/panel-header2.js +1 -1
- package/dist/workspace/utils/comparison.utils.d.ts +3 -0
- package/dist/workspace/utils/comparison.utils.js +13 -0
- package/dist/workspace/utils/comparison.utils.js.map +1 -0
- package/dist/workspace/utils/evaluation.utils.d.ts +65 -6
- package/dist/workspace/utils/evaluation.utils.js +334 -99
- package/dist/workspace/utils/evaluation.utils.js.map +1 -1
- package/dist/workspace/utils/geometry/allocation.utils.js +15 -13
- package/dist/workspace/utils/geometry/allocation.utils.js.map +1 -1
- package/dist/workspace/utils/geometry/sizing.utils.d.ts +2 -0
- package/dist/workspace/utils/geometry/sizing.utils.js +37 -17
- package/dist/workspace/utils/geometry/sizing.utils.js.map +1 -1
- package/dist/workspace/utils/interaction/boundary.utils.d.ts +2 -2
- package/dist/workspace/utils/interaction/boundary.utils.js +2 -2
- package/dist/workspace/utils/interaction/boundary.utils.js.map +1 -1
- package/dist/workspace/utils/interaction/drag-preview.utils.d.ts +3 -3
- package/dist/workspace/utils/interaction/drag-preview.utils.js.map +1 -1
- package/dist/workspace/utils/interaction/insertion-offers.utils.d.ts +11 -9
- package/dist/workspace/utils/interaction/insertion-offers.utils.js +37 -43
- package/dist/workspace/utils/interaction/insertion-offers.utils.js.map +1 -1
- package/dist/workspace/utils/interaction/placement-decision.utils.d.ts +6 -1
- package/dist/workspace/utils/interaction/placement-decision.utils.js +94 -87
- package/dist/workspace/utils/interaction/placement-decision.utils.js.map +1 -1
- package/dist/workspace/utils/model/layout.utils.d.ts +2 -1
- package/dist/workspace/utils/model/layout.utils.js +12 -10
- package/dist/workspace/utils/model/layout.utils.js.map +1 -1
- package/dist/workspace/utils/model/membership.utils.d.ts +4 -0
- package/dist/workspace/utils/model/membership.utils.js +13 -4
- package/dist/workspace/utils/model/membership.utils.js.map +1 -1
- package/dist/workspace/utils/model/operations.utils.d.ts +1 -0
- package/dist/workspace/utils/model/operations.utils.js +51 -46
- package/dist/workspace/utils/model/operations.utils.js.map +1 -1
- package/dist/workspace/utils/model/projection.utils.d.ts +4 -2
- package/dist/workspace/utils/model/projection.utils.js +49 -40
- package/dist/workspace/utils/model/projection.utils.js.map +1 -1
- package/dist/workspace/utils/model/value.utils.d.ts +4 -3
- package/dist/workspace/utils/model/value.utils.js +15 -50
- package/dist/workspace/utils/model/value.utils.js.map +1 -1
- package/dist/workspace/utils/placement/acquisition-sizing.utils.d.ts +2 -0
- package/dist/workspace/utils/placement/acquisition-sizing.utils.js +30 -22
- package/dist/workspace/utils/placement/acquisition-sizing.utils.js.map +1 -1
- package/dist/workspace/utils/placement/group-insertion.utils.d.ts +19 -13
- package/dist/workspace/utils/placement/group-insertion.utils.js +50 -47
- package/dist/workspace/utils/placement/group-insertion.utils.js.map +1 -1
- package/dist/workspace/utils/placement/planner.utils.d.ts +13 -2
- package/dist/workspace/utils/placement/planner.utils.js +79 -73
- package/dist/workspace/utils/placement/planner.utils.js.map +1 -1
- package/dist/workspace/utils/placement/preparation.utils.d.ts +5 -2
- package/dist/workspace/utils/placement/preparation.utils.js +45 -41
- package/dist/workspace/utils/placement/preparation.utils.js.map +1 -1
- package/dist/workspace/utils/placement/region.utils.js +32 -32
- package/dist/workspace/utils/placement/region.utils.js.map +1 -1
- package/dist/workspace/utils/placement/scope.utils.d.ts +34 -0
- package/dist/workspace/utils/placement/scope.utils.js +155 -0
- package/dist/workspace/utils/placement/scope.utils.js.map +1 -0
- package/dist/workspace/utils/placement/session.utils.d.ts +11 -0
- package/dist/workspace/utils/placement/session.utils.js +78 -0
- package/dist/workspace/utils/placement/session.utils.js.map +1 -0
- package/dist/workspace/utils/placement/split-sizing.utils.d.ts +2 -2
- package/dist/workspace/utils/placement/split-sizing.utils.js +19 -19
- package/dist/workspace/utils/placement/split-sizing.utils.js.map +1 -1
- package/dist/workspace/utils/presentation/composition.utils.d.ts +1 -1
- package/dist/workspace/utils/presentation/composition.utils.js +4 -2
- package/dist/workspace/utils/presentation/composition.utils.js.map +1 -1
- package/dist/workspace/utils/presentation/groups.utils.d.ts +3 -3
- package/dist/workspace/utils/presentation/groups.utils.js +40 -30
- package/dist/workspace/utils/presentation/groups.utils.js.map +1 -1
- package/dist/workspace/utils/presentation/measurements.utils.d.ts +1 -0
- package/dist/workspace/utils/presentation/measurements.utils.js +6 -14
- package/dist/workspace/utils/presentation/measurements.utils.js.map +1 -1
- package/dist/workspace/utils/presentation/offers.utils.d.ts +1 -1
- package/dist/workspace/utils/presentation/offers.utils.js +3 -3
- package/dist/workspace/utils/presentation/offers.utils.js.map +1 -1
- package/dist/workspace/utils/presentation/preview.utils.d.ts +6 -0
- package/dist/workspace/utils/presentation/preview.utils.js +14 -3
- package/dist/workspace/utils/presentation/preview.utils.js.map +1 -1
- package/dist/workspace/workspace.examples.js.map +1 -1
- package/dist/workspace/workspace.examples.json +4 -4
- package/dist/workspace/workspace.js +1 -1
- package/dist/workspace/workspace.js.map +1 -1
- package/dist/workspace/workspace2.js +206 -212
- package/dist/workspace/workspace2.js.map +1 -1
- package/package.json +1 -1
- package/dist/workspace/utils/placement/context.utils.d.ts +0 -36
- package/dist/workspace/utils/placement/context.utils.js +0 -135
- package/dist/workspace/utils/placement/context.utils.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"value.utils.js","names":["
|
|
1
|
+
{"version":3,"file":"value.utils.js","names":["parseWorkspaceValue","value","data","ids","record","item","node","id","splitShape","child","normalizeLayout","serializeWorkspaceValue","layout","weight","sum","sameWorkspaceLayout","left","right","sameArrayItems","sameWorkspaceNode","index"],"sources":["../../../../src/workspace/utils/model/value.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { normalizeLayout } from './layout.utils.js';\nimport { sameArrayItems } from '../comparison.utils.js';\n\nimport type { WorkspaceLayout, WorkspaceNode, WorkspaceSplit } from './layout.utils.js';\n\nexport function parseWorkspaceValue(value: string): WorkspaceLayout | undefined {\n if (!value) return undefined;\n\n const data: unknown = JSON.parse(value);\n const ids = new Set<string>();\n const record = (item: unknown): item is Record<string, unknown> => typeof item === 'object' && item !== null;\n const node = (item: unknown): item is WorkspaceNode => {\n if (!record(item)) return false;\n if (item.type === 'group') {\n if (\n !Array.isArray(item.panels) ||\n !item.panels.length ||\n typeof item.active !== 'string' ||\n !item.panels.includes(item.active)\n ) {\n return false;\n }\n return item.panels.every(id => {\n if (typeof id !== 'string' || !id || ids.has(id)) return false;\n ids.add(id);\n return true;\n });\n }\n if (!splitShape(item)) return false;\n return item.children.every(child => node(child));\n };\n if (\n !record(data) ||\n data.version !== 1 ||\n !(data.root === null || node(data.root)) ||\n !Array.isArray(data.closed) ||\n !data.closed.every(id => typeof id === 'string' && ids.has(id)) ||\n new Set(data.closed).size !== data.closed.length\n ) {\n throw new TypeError('Invalid workspace arrangement');\n }\n return { version: 1, root: data.root === null ? null : normalizeLayout(data.root), closed: [...data.closed] };\n}\n\nexport function serializeWorkspaceValue(layout: WorkspaceLayout | undefined): string {\n return layout ? JSON.stringify(layout) : '';\n}\n\nfunction splitShape(item: Record<string, unknown>): item is Record<string, unknown> & WorkspaceSplit {\n if (item.type !== 'split' || !['horizontal', 'vertical'].includes(String(item.axis))) return false;\n if (!Array.isArray(item.children) || item.children.length < 2) return false;\n if (!Array.isArray(item.weights) || item.weights.length !== item.children.length) return false;\n if (!item.weights.every(weight => typeof weight === 'number' && Number.isFinite(weight) && weight > 0)) return false;\n return Number.isFinite(item.weights.reduce((sum: number, weight: number) => sum + weight, 0));\n}\n\n/** Compares known arrangement fields; object property insertion order is irrelevant. */\nexport function sameWorkspaceLayout(left: WorkspaceLayout | undefined, right: WorkspaceLayout | undefined): boolean {\n if (left === right) return true;\n if (!left || !right) return false;\n return (\n left.version === right.version &&\n sameArrayItems(left.closed, right.closed) &&\n sameWorkspaceNode(left.root, right.root)\n );\n}\n\n// eslint-disable-next-line complexity -- Compare the owned node fields directly without comparison callbacks.\nexport function sameWorkspaceNode(left: WorkspaceNode | null, right: WorkspaceNode | null): boolean {\n if (left === right) return true;\n if (!left || !right) return false;\n if (left.type === 'group') {\n return right.type === 'group' && left.active === right.active && sameArrayItems(left.panels, right.panels);\n }\n if (\n right.type !== 'split' ||\n left.axis !== right.axis ||\n !sameArrayItems(left.weights, right.weights) ||\n left.children.length !== right.children.length\n )\n return false;\n for (let index = 0; index < left.children.length; index++) {\n if (!sameWorkspaceNode(left.children[index]!, right.children[index]!)) return false;\n }\n return true;\n}\n"],"mappings":";;;AAQA,SAAgBA,EAAoB,GAA4C;CAC9E,IAAI,CAACC,GAAO;CAEZ,IAAMC,IAAgB,KAAK,MAAMD,CAAK,GAChCE,oBAAM,IAAI,IAAY,GACtBC,KAAU,MAAmD,OAAOC,KAAS,cAAYA,GACzFC,KAAQ,MACPF,EAAOC,CAAI,IACZA,EAAK,SAAS,UAEd,CAAC,MAAM,QAAQA,EAAK,MAAM,KAC1B,CAACA,EAAK,OAAO,UACb,OAAOA,EAAK,UAAW,YACvB,CAACA,EAAK,OAAO,SAASA,EAAK,MAAM,IAE1B,KAEFA,EAAK,OAAO,OAAM,MACnB,OAAOE,KAAO,YAAY,CAACA,KAAMJ,EAAI,IAAII,CAAE,IAAU,MACzDJ,EAAI,IAAII,CAAE,GACH,GACR,IAEEC,EAAWH,CAAI,IACbA,EAAK,SAAS,OAAM,MAASC,EAAKG,CAAK,CAAC,IADjB,KAhBJ;CAmB5B,IACE,CAACL,EAAOF,CAAI,KACZA,EAAK,YAAY,KACjB,EAAEA,EAAK,SAAS,QAAQI,EAAKJ,EAAK,IAAI,MACtC,CAAC,MAAM,QAAQA,EAAK,MAAM,KAC1B,CAACA,EAAK,OAAO,OAAM,MAAM,OAAOK,KAAO,YAAYJ,EAAI,IAAII,CAAE,CAAC,KAC9D,IAAI,IAAIL,EAAK,MAAM,CAAC,CAAC,SAASA,EAAK,OAAO,QAE1C,MAAU,UAAU,+BAA+B;CAErD,OAAO;EAAE,SAAS;EAAG,MAAMA,EAAK,SAAS,OAAO,OAAOQ,EAAgBR,EAAK,IAAI;EAAG,QAAQ,CAAC,GAAGA,EAAK,MAAM;CAAE;AAC9G;AAEA,SAAgBS,EAAwB,GAA6C;CACnF,OAAOC,IAAS,KAAK,UAAUA,CAAM,IAAI;AAC3C;AAEA,SAASJ,EAAW,GAAiF;CAKnG,OAJIH,EAAK,SAAS,WAAW,CAAC,CAAC,cAAc,UAAU,CAAC,CAAC,SAAS,OAAOA,EAAK,IAAI,CAAC,KAC/E,CAAC,MAAM,QAAQA,EAAK,QAAQ,KAAKA,EAAK,SAAS,SAAS,KACxD,CAAC,MAAM,QAAQA,EAAK,OAAO,KAAKA,EAAK,QAAQ,WAAWA,EAAK,SAAS,UACtE,CAACA,EAAK,QAAQ,OAAM,MAAU,OAAOQ,KAAW,YAAY,OAAO,SAASA,CAAM,KAAKA,IAAS,CAAC,IAAU,KACxG,OAAO,SAASR,EAAK,QAAQ,QAAQ,GAAa,MAAmBS,IAAMD,GAAQ,CAAC,CAAC;AAC9F;AAGA,SAAgBE,EAAoB,GAAmC,GAA6C;CAGlH,OAFIC,MAASC,IAAc,KACvB,CAACD,KAAQ,CAACC,IAAc,KAE1BD,EAAK,YAAYC,EAAM,WACvBC,EAAeF,EAAK,QAAQC,EAAM,MAAM,KACxCE,EAAkBH,EAAK,MAAMC,EAAM,IAAI;AAE3C;AAGA,SAAgBE,EAAkB,GAA4B,GAAsC;CAClG,IAAIH,MAASC,GAAO,OAAO;CAC3B,IAAI,CAACD,KAAQ,CAACC,GAAO,OAAO;CAC5B,IAAID,EAAK,SAAS,SAChB,OAAOC,EAAM,SAAS,WAAWD,EAAK,WAAWC,EAAM,UAAUC,EAAeF,EAAK,QAAQC,EAAM,MAAM;CAE3G,IACEA,EAAM,SAAS,WACfD,EAAK,SAASC,EAAM,QACpB,CAACC,EAAeF,EAAK,SAASC,EAAM,OAAO,KAC3CD,EAAK,SAAS,WAAWC,EAAM,SAAS,QAExC,OAAO;CACT,KAAK,IAAIG,IAAQ,GAAGA,IAAQJ,EAAK,SAAS,QAAQ,KAChD,IAAI,CAACG,EAAkBH,EAAK,SAASI,IAASH,EAAM,SAASG,EAAO,GAAG,OAAO;CAEhF,OAAO;AACT"}
|
|
@@ -4,7 +4,9 @@ import type { WorkspaceRequirements } from '../geometry/sizing.utils.js';
|
|
|
4
4
|
import type { WorkspaceDragPreview, WorkspaceDropIntent } from '../interaction/drag-preview.utils.js';
|
|
5
5
|
import type { WorkspaceLayout } from '../model/layout.utils.js';
|
|
6
6
|
import type { WorkspacePlacementPlan } from './planner.utils.js';
|
|
7
|
+
import type { WorkspacePlacementSession } from './session.utils.js';
|
|
7
8
|
interface AcquisitionInput {
|
|
9
|
+
placementSession?: WorkspacePlacementSession;
|
|
8
10
|
plan: WorkspacePlacementPlan;
|
|
9
11
|
previous: WorkspaceLayout;
|
|
10
12
|
source: string[];
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { getPanelIds as e } from "../model/layout.utils.js";
|
|
2
2
|
import { projectLayout as t } from "../model/operations.utils.js";
|
|
3
3
|
import { matchesPlacementIntent as n } from "../interaction/drag-preview.utils.js";
|
|
4
|
-
import {
|
|
5
|
-
import { rebaseProjectedSplit as
|
|
6
|
-
import {
|
|
4
|
+
import { samePanelMembership as r } from "../model/membership.utils.js";
|
|
5
|
+
import { rebaseProjectedSplit as i } from "../model/projection.utils.js";
|
|
6
|
+
import { getAllocatedScopeRect as a } from "./scope.utils.js";
|
|
7
|
+
import { getGroupInsertion as o } from "./group-insertion.utils.js";
|
|
7
8
|
import { getMinimumWorkspaceDimensions as s } from "../geometry/sizing.utils.js";
|
|
8
9
|
import { fitSizes as c } from "../geometry/partition.utils.js";
|
|
9
10
|
import { allocateWorkspace as l } from "../geometry/allocation.utils.js";
|
|
@@ -24,7 +25,7 @@ function u(e) {
|
|
|
24
25
|
} : void 0;
|
|
25
26
|
}
|
|
26
27
|
function d(e, t) {
|
|
27
|
-
return !!e?.previous && !!e.next && !!t && (e.axis !== t.axis ||
|
|
28
|
+
return !!e?.previous && !!e.next && !!t && (e.axis !== t.axis || !r(e.members, t.members));
|
|
28
29
|
}
|
|
29
30
|
function f(e, t) {
|
|
30
31
|
return !!t && e.covers(t, "x") && e.covers(t, "y");
|
|
@@ -36,20 +37,27 @@ function p(e, n) {
|
|
|
36
37
|
} : {
|
|
37
38
|
start: e.acquisition.point[t],
|
|
38
39
|
end: e.acquisition.point[t]
|
|
39
|
-
};
|
|
40
|
+
}, o;
|
|
40
41
|
return {
|
|
41
42
|
input: e,
|
|
42
43
|
axis: r,
|
|
43
44
|
extent: i,
|
|
44
45
|
range: a,
|
|
45
46
|
covers: (e, t) => m(e, t, a(t)),
|
|
46
|
-
allocate: (n) =>
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
allocate: (n) => {
|
|
48
|
+
if (o?.layout === n) return o.allocation;
|
|
49
|
+
let r = l({
|
|
50
|
+
root: t(n, e.available).root,
|
|
51
|
+
rect: e.rect,
|
|
52
|
+
minimum: (t) => s(t, e.requirements),
|
|
53
|
+
policy: "stop",
|
|
54
|
+
gap: e.requirements.gap
|
|
55
|
+
});
|
|
56
|
+
return o = {
|
|
57
|
+
layout: n,
|
|
58
|
+
allocation: r
|
|
59
|
+
}, r;
|
|
60
|
+
}
|
|
53
61
|
};
|
|
54
62
|
}
|
|
55
63
|
function m(e, t, n) {
|
|
@@ -72,30 +80,30 @@ function h(e, t) {
|
|
|
72
80
|
}
|
|
73
81
|
return r;
|
|
74
82
|
}
|
|
75
|
-
function g({ fit: t, layout: n, parent:
|
|
76
|
-
if (
|
|
77
|
-
let l =
|
|
83
|
+
function g({ fit: t, layout: n, parent: r, index: o }) {
|
|
84
|
+
if (r.node.type !== "split") return;
|
|
85
|
+
let l = r.node.axis === "horizontal" ? "width" : "height", u = r.node.children.map((e) => s(e, t.input.requirements)[l]), d = r.rect[l] - t.input.requirements.gap * (u.length - 1), f = r.node.children.map((n, r) => r === o ? 0 : a({
|
|
78
86
|
members: e(n),
|
|
79
87
|
allocation: t.input.current,
|
|
80
88
|
source: t.input.source
|
|
81
89
|
})?.[l]);
|
|
82
90
|
if (f.some((e) => e === void 0) || y(u) > d) return;
|
|
83
91
|
let p = f.map((e) => e);
|
|
84
|
-
return p[o] = Math.max(u[o], d - y(p)),
|
|
92
|
+
return p[o] = Math.max(u[o], d - y(p)), i(n, r.node, c(p, u, d), t.input.available) ?? n;
|
|
85
93
|
}
|
|
86
94
|
function _(e, t, n) {
|
|
87
|
-
let r = e.allocate(t),
|
|
88
|
-
if (
|
|
95
|
+
let r = e.allocate(t), a = r.regions.find((e) => e.key === n.split(".").slice(0, -1).join("."));
|
|
96
|
+
if (a.node.type !== "split") return;
|
|
89
97
|
let o = r.groups.find((e) => e.key === n), s = Number(n.split(".").at(-1)), c = v({
|
|
90
98
|
fit: e,
|
|
91
99
|
owner: {
|
|
92
|
-
...
|
|
93
|
-
node:
|
|
100
|
+
...a,
|
|
101
|
+
node: a.node
|
|
94
102
|
},
|
|
95
103
|
incoming: o.rect,
|
|
96
104
|
index: s
|
|
97
105
|
});
|
|
98
|
-
if (c) return
|
|
106
|
+
if (c) return i(t, a.node, c, e.input.available) ?? t;
|
|
99
107
|
}
|
|
100
108
|
function v(e) {
|
|
101
109
|
let { fit: t, owner: n, incoming: r, index: i } = e, { axis: a, extent: o } = t, l = n.node.children.map((e) => s(e, t.input.requirements)[o]), u = l.slice(0, i), d = l.slice(i + 1), f = Math.max(n.rect[a] + y(u) + t.input.requirements.gap * i, t.range(a).end - r[o]), p = Math.min(n.rect[a] + n.rect[o] - y(d) - t.input.requirements.gap * d.length - r[o], t.range(a).start);
|
|
@@ -142,7 +150,7 @@ function x(e, t) {
|
|
|
142
150
|
return ["order", "insert"].includes(e.intent.kind) && ["insert", "reorder"].includes(t.kind);
|
|
143
151
|
}
|
|
144
152
|
function S(e, t) {
|
|
145
|
-
return e?.phase === "detached" && !e.blocked && e.allocation === "reserved" &&
|
|
153
|
+
return e?.phase === "detached" && !e.blocked && e.allocation === "reserved" && r(e.source, t);
|
|
146
154
|
}
|
|
147
155
|
function C(e, t) {
|
|
148
156
|
return e?.phase === "detached" && e.blocked && n(e.intent, t);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acquisition-sizing.utils.js","names":["fitAcquiredPlacement","next","describePlacementSlot","input","crossScopeInterior","fit","acquisitionFit","moving","group","id","coversAcquisition","ancestors","fitReceivingPath","layout","fitIncoming","achieved","prior","getContextKey","rect","axis","direction","extent","range","dimension","coversRange","allocateWorkspace","projectLayout","getMinimumWorkspaceDimensions","node","end","path","depth","key","regions","parent","region","receiving","fitAncestor","size","minima","child","budget","extents","slot","index","getAllocatedContextRect","getPanelIds","value","sum","preferred","rebaseProjectedSplit","fitSizes","allocation","owner","incoming","sizes","incomingSizes","before","after","start","position","values","total","resolveSelectedPlacementPlan","blockedSelection","selectedReservation","spatialReservation","current","point","preview","plan","source","matchesPlacementIntent","intent"],"sources":["../../../../src/workspace/utils/placement/acquisition-sizing.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Point, Rect } from '@nvidia-elements/core/internal';\n\nimport { allocateWorkspace } from '../geometry/allocation.utils.js';\nimport { fitSizes } from '../geometry/partition.utils.js';\nimport { getMinimumWorkspaceDimensions } from '../geometry/sizing.utils.js';\nimport { matchesPlacementIntent } from '../interaction/drag-preview.utils.js';\nimport { getPanelIds } from '../model/layout.utils.js';\nimport { projectLayout } from '../model/operations.utils.js';\nimport { rebaseProjectedSplit } from '../model/projection.utils.js';\nimport { getAllocatedContextRect, getContextKey } from './context.utils.js';\nimport { describePlacementSlot } from './group-insertion.utils.js';\n\nimport type { WorkspacePlacedRegion } from '../geometry/allocation.utils.js';\nimport type { WorkspaceRequirements } from '../geometry/sizing.utils.js';\nimport type { WorkspaceDragPreview, WorkspaceDropIntent } from '../interaction/drag-preview.utils.js';\nimport type { WorkspaceLayout, WorkspaceSplit } from '../model/layout.utils.js';\nimport type { WorkspacePlacementPlan } from './planner.utils.js';\n\ninterface AcquisitionInput {\n plan: WorkspacePlacementPlan;\n previous: WorkspaceLayout;\n source: string[];\n available: string[];\n current: WorkspacePlacedRegion[];\n rect: Rect;\n acquisition: { rect: Rect; point: Point };\n requirements: WorkspaceRequirements;\n}\n\ninterface Fit {\n input: AcquisitionInput;\n axis: 'x' | 'y';\n extent: 'width' | 'height';\n range: (axis: 'x' | 'y') => { start: number; end: number };\n covers: (rect: Rect, axis: 'x' | 'y') => boolean;\n allocate: (layout: WorkspaceLayout) => ReturnType<typeof allocateWorkspace>;\n}\n\n/** Fits a cross-scope interior reservation to its acquired allocation without retaining a hidden target. */\nexport function fitAcquiredPlacement(input: AcquisitionInput): WorkspacePlacementPlan | undefined {\n const next = describePlacementSlot(input);\n const prior = describePlacementSlot({ ...input, plan: { layout: input.previous } });\n if (!crossScopeInterior(next, prior)) return input.plan;\n const fit = acquisitionFit(input, next.axis);\n const moving = fit\n .allocate(input.plan.layout)\n .groups.find(group => group.group.panels.every(id => input.source.includes(id)));\n if (!moving) return undefined;\n if (coversAcquisition(fit, moving.rect)) return input.plan;\n const ancestors = fitReceivingPath(fit, moving.key);\n const layout = ancestors && fitIncoming(fit, ancestors, moving.key);\n const achieved = layout && fit.allocate(layout).groups.find(group => group.key === moving.key);\n return layout && coversAcquisition(fit, achieved?.rect) ? { ...input.plan, layout } : undefined;\n}\n\nfunction crossScopeInterior(\n next: ReturnType<typeof describePlacementSlot>,\n prior: ReturnType<typeof describePlacementSlot>\n): next is NonNullable<typeof next> {\n return (\n !!next?.previous &&\n !!next.next &&\n !!prior &&\n (next.axis !== prior.axis || getContextKey(next.members) !== getContextKey(prior.members))\n );\n}\n\nfunction coversAcquisition(fit: Fit, rect?: Rect) {\n return !!rect && fit.covers(rect, 'x') && fit.covers(rect, 'y');\n}\n\nfunction acquisitionFit(input: AcquisitionInput, direction: WorkspaceSplit['axis']): Fit {\n const axis = direction === 'horizontal' ? 'x' : 'y';\n const extent = axis === 'x' ? 'width' : 'height';\n const range = (dimension: 'x' | 'y') =>\n dimension === axis\n ? { start: input.acquisition.rect[axis], end: input.acquisition.rect[axis] + input.acquisition.rect[extent] }\n : { start: input.acquisition.point[dimension], end: input.acquisition.point[dimension] };\n return {\n input,\n axis,\n extent,\n range,\n covers: (rect, dimension) => coversRange(rect, dimension, range(dimension)),\n allocate: layout =>\n allocateWorkspace({\n root: projectLayout(layout, input.available).root,\n rect: input.rect,\n minimum: node => getMinimumWorkspaceDimensions(node, input.requirements),\n policy: 'stop',\n gap: input.requirements.gap\n })\n };\n}\n\nfunction coversRange(rect: Rect, axis: 'x' | 'y', range: { start: number; end: number }) {\n const end = rect[axis] + rect[axis === 'x' ? 'width' : 'height'];\n return range.start === range.end\n ? rect[axis] <= range.start && range.start < end\n : rect[axis] <= range.start + 1e-7 && end >= range.end - 1e-7;\n}\n\nfunction fitReceivingPath(fit: Fit, moving: string) {\n const path = moving.split('.');\n let layout: WorkspaceLayout | undefined = fit.input.plan.layout;\n for (let depth = 1; depth < path.length - 1; depth++) {\n if (!layout) return undefined;\n const key = path.slice(0, depth).join('.');\n const regions = fit.allocate(layout).regions;\n const parent = regions.find(region => region.key === key)!;\n const receiving = regions.find(region => region.key === `${key}.${path[depth]}`)!;\n if (parent.node.type !== 'split') return undefined;\n const axis = parent.node.axis === 'horizontal' ? 'x' : 'y';\n if (!fit.covers(receiving.rect, axis)) {\n layout = fitAncestor({ fit, layout, parent, index: Number(path[depth]) });\n }\n }\n return layout;\n}\n\nfunction fitAncestor({\n fit,\n layout,\n parent,\n index\n}: {\n fit: Fit;\n layout: WorkspaceLayout;\n parent: WorkspacePlacedRegion;\n index: number;\n}) {\n if (parent.node.type !== 'split') return undefined;\n const size = parent.node.axis === 'horizontal' ? 'width' : 'height';\n const minima = parent.node.children.map(child => getMinimumWorkspaceDimensions(child, fit.input.requirements)[size]);\n const budget = parent.rect[size] - fit.input.requirements.gap * (minima.length - 1);\n const extents = parent.node.children.map((child, slot) =>\n slot === index\n ? 0\n : getAllocatedContextRect({\n members: getPanelIds(child),\n allocation: fit.input.current,\n source: fit.input.source\n })?.[size]\n );\n if (extents.some(value => value === undefined) || sum(minima) > budget) return undefined;\n const preferred = extents.map(value => value!);\n preferred[index] = Math.max(minima[index]!, budget - sum(preferred));\n return rebaseProjectedSplit(layout, parent.node, fitSizes(preferred, minima, budget), fit.input.available) ?? layout;\n}\n\nfunction fitIncoming(fit: Fit, layout: WorkspaceLayout, key: string) {\n const allocation = fit.allocate(layout);\n const owner = allocation.regions.find(region => region.key === key.split('.').slice(0, -1).join('.'))!;\n if (owner.node.type !== 'split') return undefined;\n const incoming = allocation.groups.find(group => group.key === key)!;\n const index = Number(key.split('.').at(-1));\n const sizes = incomingSizes({ fit, owner: { ...owner, node: owner.node }, incoming: incoming.rect, index });\n if (!sizes) return undefined;\n\n const rebased = rebaseProjectedSplit(layout, owner.node, sizes, fit.input.available);\n return rebased ?? layout;\n}\n\nfunction incomingSizes(input: {\n fit: Fit;\n owner: WorkspacePlacedRegion & { node: WorkspaceSplit };\n incoming: Rect;\n index: number;\n}) {\n const { fit, owner, incoming, index } = input;\n const { axis, extent } = fit;\n const minima = owner.node.children.map(child => getMinimumWorkspaceDimensions(child, fit.input.requirements)[extent]);\n const before = minima.slice(0, index);\n const after = minima.slice(index + 1);\n const start = Math.max(\n owner.rect[axis] + sum(before) + fit.input.requirements.gap * index,\n fit.range(axis).end - incoming[extent]\n );\n const end = Math.min(\n owner.rect[axis] + owner.rect[extent] - sum(after) - fit.input.requirements.gap * after.length - incoming[extent],\n fit.range(axis).start\n );\n if (start > end) return undefined;\n const position = Math.max(start, Math.min(incoming[axis], end));\n return [\n ...fitSizes(\n owner.node.weights.slice(0, index),\n before,\n position - owner.rect[axis] - fit.input.requirements.gap * index\n ),\n incoming[extent],\n ...fitSizes(\n owner.node.weights.slice(index + 1),\n after,\n owner.rect[axis] + owner.rect[extent] - position - incoming[extent] - fit.input.requirements.gap * after.length\n )\n ];\n}\n\nconst sum = (values: number[]) => values.reduce((total, value) => total + value, 0);\n\n/** Reuses the actual selected reservation before considering a different spatial offer. */\nexport function resolveSelectedPlacementPlan(\n input: Omit<AcquisitionInput, 'previous' | 'acquisition'> & {\n previous?: WorkspaceDragPreview;\n acquisition?: { rect: Rect; point: Point };\n clientOrigin: Rect;\n intent: WorkspaceDropIntent;\n }\n): WorkspacePlacementPlan | undefined {\n const prior = input.previous;\n if (blockedSelection(prior, input.intent) && !input.acquisition) return undefined;\n if (!selectedReservation(prior, input.source) || !spatialReservation(prior, input.plan)) return input.plan;\n const current = describePlacementSlot({ ...input, plan: prior });\n const next = describePlacementSlot(input);\n if (current && current.key === next?.key) return { ...input.plan, layout: prior.layout };\n if (!input.acquisition) return input.plan;\n const { rect, point } = input.acquisition;\n return fitAcquiredPlacement({\n ...input,\n previous: prior.layout,\n acquisition: {\n rect: { ...rect, x: rect.x - input.clientOrigin.x, y: rect.y - input.clientOrigin.y },\n point: { x: point.x - input.clientOrigin.x, y: point.y - input.clientOrigin.y }\n }\n });\n}\n\nfunction spatialReservation(preview: WorkspaceDragPreview, plan: WorkspacePlacementPlan) {\n return ['order', 'insert'].includes(preview.intent.kind) && ['insert', 'reorder'].includes(plan.kind);\n}\n\nfunction selectedReservation(\n preview: WorkspaceDragPreview | undefined,\n source: string[]\n): preview is Extract<WorkspaceDragPreview, { phase: 'detached' }> & { allocation: 'reserved' } {\n return (\n preview?.phase === 'detached' &&\n !preview.blocked &&\n preview.allocation === 'reserved' &&\n getContextKey(preview.source) === getContextKey(source)\n );\n}\n\nfunction blockedSelection(preview: WorkspaceDragPreview | undefined, intent: WorkspaceDropIntent) {\n return preview?.phase === 'detached' && preview.blocked && matchesPlacementIntent(preview.intent, intent);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"acquisition-sizing.utils.js","names":["fitAcquiredPlacement","next","getGroupInsertion","input","crossScopeInterior","fit","acquisitionFit","moving","group","id","coversAcquisition","ancestors","fitReceivingPath","layout","fitIncoming","achieved","prior","samePanelMembership","rect","axis","direction","extent","range","dimension","lastAllocation","coversRange","allocation","allocateWorkspace","projectLayout","getMinimumWorkspaceDimensions","node","end","path","depth","key","regions","parent","region","receiving","fitAncestor","size","minima","child","budget","extents","childIndex","index","getAllocatedScopeRect","getPanelIds","value","sum","preferred","rebaseProjectedSplit","fitSizes","owner","incoming","sizes","incomingSizes","before","after","start","position","values","total","resolveSelectedPlacementPlan","blockedSelection","selectedReservation","spatialReservation","current","point","preview","plan","source","matchesPlacementIntent","intent"],"sources":["../../../../src/workspace/utils/placement/acquisition-sizing.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Point, Rect } from '@nvidia-elements/core/internal';\n\nimport { allocateWorkspace } from '../geometry/allocation.utils.js';\nimport { fitSizes } from '../geometry/partition.utils.js';\nimport { getMinimumWorkspaceDimensions } from '../geometry/sizing.utils.js';\nimport { matchesPlacementIntent } from '../interaction/drag-preview.utils.js';\nimport { getPanelIds } from '../model/layout.utils.js';\nimport { samePanelMembership } from '../model/membership.utils.js';\nimport { projectLayout } from '../model/operations.utils.js';\nimport { rebaseProjectedSplit } from '../model/projection.utils.js';\nimport { getGroupInsertion } from './group-insertion.utils.js';\nimport { getAllocatedScopeRect } from './scope.utils.js';\n\nimport type { WorkspacePlacedRegion } from '../geometry/allocation.utils.js';\nimport type { WorkspaceRequirements } from '../geometry/sizing.utils.js';\nimport type { WorkspaceDragPreview, WorkspaceDropIntent } from '../interaction/drag-preview.utils.js';\nimport type { WorkspaceLayout, WorkspaceSplit } from '../model/layout.utils.js';\nimport type { GroupInsertion } from './group-insertion.utils.js';\nimport type { WorkspacePlacementPlan } from './planner.utils.js';\nimport type { WorkspacePlacementSession } from './session.utils.js';\n\ninterface AcquisitionInput {\n placementSession?: WorkspacePlacementSession;\n plan: WorkspacePlacementPlan;\n previous: WorkspaceLayout;\n source: string[];\n available: string[];\n current: WorkspacePlacedRegion[];\n rect: Rect;\n acquisition: { rect: Rect; point: Point };\n requirements: WorkspaceRequirements;\n}\n\ninterface Fit {\n input: AcquisitionInput;\n axis: 'x' | 'y';\n extent: 'width' | 'height';\n range: (axis: 'x' | 'y') => { start: number; end: number };\n covers: (rect: Rect, axis: 'x' | 'y') => boolean;\n allocate: (layout: WorkspaceLayout) => ReturnType<typeof allocateWorkspace>;\n}\n\n/** Fits a cross-scope interior reservation to its acquired allocation without retaining a hidden target. */\nexport function fitAcquiredPlacement(input: AcquisitionInput): WorkspacePlacementPlan | undefined {\n const next = getGroupInsertion(input);\n const prior = getGroupInsertion({ ...input, plan: { layout: input.previous } });\n if (!crossScopeInterior(next, prior)) return input.plan;\n const fit = acquisitionFit(input, next.axis);\n const moving = fit\n .allocate(input.plan.layout)\n .groups.find(group => group.group.panels.every(id => input.source.includes(id)));\n if (!moving) return undefined;\n if (coversAcquisition(fit, moving.rect)) return input.plan;\n const ancestors = fitReceivingPath(fit, moving.key);\n const layout = ancestors && fitIncoming(fit, ancestors, moving.key);\n const achieved = layout && fit.allocate(layout).groups.find(group => group.key === moving.key);\n return layout && coversAcquisition(fit, achieved?.rect) ? { ...input.plan, layout } : undefined;\n}\n\nfunction crossScopeInterior(\n next: GroupInsertion | undefined,\n prior: GroupInsertion | undefined\n): next is NonNullable<typeof next> {\n return (\n !!next?.previous &&\n !!next.next &&\n !!prior &&\n (next.axis !== prior.axis || !samePanelMembership(next.members, prior.members))\n );\n}\n\nfunction coversAcquisition(fit: Fit, rect?: Rect) {\n return !!rect && fit.covers(rect, 'x') && fit.covers(rect, 'y');\n}\n\nfunction acquisitionFit(input: AcquisitionInput, direction: WorkspaceSplit['axis']): Fit {\n const axis = direction === 'horizontal' ? 'x' : 'y';\n const extent = axis === 'x' ? 'width' : 'height';\n const range = (dimension: 'x' | 'y') =>\n dimension === axis\n ? { start: input.acquisition.rect[axis], end: input.acquisition.rect[axis] + input.acquisition.rect[extent] }\n : { start: input.acquisition.point[dimension], end: input.acquisition.point[dimension] };\n let lastAllocation: { layout: WorkspaceLayout; allocation: ReturnType<typeof allocateWorkspace> } | undefined;\n return {\n input,\n axis,\n extent,\n range,\n covers: (rect, dimension) => coversRange(rect, dimension, range(dimension)),\n allocate: layout => {\n if (lastAllocation?.layout === layout) return lastAllocation.allocation;\n const allocation = allocateWorkspace({\n root: projectLayout(layout, input.available).root,\n rect: input.rect,\n minimum: node => getMinimumWorkspaceDimensions(node, input.requirements),\n policy: 'stop',\n gap: input.requirements.gap\n });\n lastAllocation = { layout, allocation };\n return allocation;\n }\n };\n}\n\nfunction coversRange(rect: Rect, axis: 'x' | 'y', range: { start: number; end: number }) {\n const end = rect[axis] + rect[axis === 'x' ? 'width' : 'height'];\n return range.start === range.end\n ? rect[axis] <= range.start && range.start < end\n : rect[axis] <= range.start + 1e-7 && end >= range.end - 1e-7;\n}\n\nfunction fitReceivingPath(fit: Fit, moving: string) {\n const path = moving.split('.');\n let layout: WorkspaceLayout | undefined = fit.input.plan.layout;\n for (let depth = 1; depth < path.length - 1; depth++) {\n if (!layout) return undefined;\n const key = path.slice(0, depth).join('.');\n const regions = fit.allocate(layout).regions;\n const parent = regions.find(region => region.key === key)!;\n const receiving = regions.find(region => region.key === `${key}.${path[depth]}`)!;\n if (parent.node.type !== 'split') return undefined;\n const axis = parent.node.axis === 'horizontal' ? 'x' : 'y';\n if (!fit.covers(receiving.rect, axis)) {\n layout = fitAncestor({ fit, layout, parent, index: Number(path[depth]) });\n }\n }\n return layout;\n}\n\nfunction fitAncestor({\n fit,\n layout,\n parent,\n index\n}: {\n fit: Fit;\n layout: WorkspaceLayout;\n parent: WorkspacePlacedRegion;\n index: number;\n}) {\n if (parent.node.type !== 'split') return undefined;\n const size = parent.node.axis === 'horizontal' ? 'width' : 'height';\n const minima = parent.node.children.map(child => getMinimumWorkspaceDimensions(child, fit.input.requirements)[size]);\n const budget = parent.rect[size] - fit.input.requirements.gap * (minima.length - 1);\n const extents = parent.node.children.map((child, childIndex) =>\n childIndex === index\n ? 0\n : getAllocatedScopeRect({\n members: getPanelIds(child),\n allocation: fit.input.current,\n source: fit.input.source\n })?.[size]\n );\n if (extents.some(value => value === undefined) || sum(minima) > budget) return undefined;\n const preferred = extents.map(value => value!);\n preferred[index] = Math.max(minima[index]!, budget - sum(preferred));\n return rebaseProjectedSplit(layout, parent.node, fitSizes(preferred, minima, budget), fit.input.available) ?? layout;\n}\n\nfunction fitIncoming(fit: Fit, layout: WorkspaceLayout, key: string) {\n const allocation = fit.allocate(layout);\n const owner = allocation.regions.find(region => region.key === key.split('.').slice(0, -1).join('.'))!;\n if (owner.node.type !== 'split') return undefined;\n const incoming = allocation.groups.find(group => group.key === key)!;\n const index = Number(key.split('.').at(-1));\n const sizes = incomingSizes({ fit, owner: { ...owner, node: owner.node }, incoming: incoming.rect, index });\n if (!sizes) return undefined;\n\n const rebased = rebaseProjectedSplit(layout, owner.node, sizes, fit.input.available);\n return rebased ?? layout;\n}\n\nfunction incomingSizes(input: {\n fit: Fit;\n owner: WorkspacePlacedRegion & { node: WorkspaceSplit };\n incoming: Rect;\n index: number;\n}) {\n const { fit, owner, incoming, index } = input;\n const { axis, extent } = fit;\n const minima = owner.node.children.map(child => getMinimumWorkspaceDimensions(child, fit.input.requirements)[extent]);\n const before = minima.slice(0, index);\n const after = minima.slice(index + 1);\n const start = Math.max(\n owner.rect[axis] + sum(before) + fit.input.requirements.gap * index,\n fit.range(axis).end - incoming[extent]\n );\n const end = Math.min(\n owner.rect[axis] + owner.rect[extent] - sum(after) - fit.input.requirements.gap * after.length - incoming[extent],\n fit.range(axis).start\n );\n if (start > end) return undefined;\n const position = Math.max(start, Math.min(incoming[axis], end));\n return [\n ...fitSizes(\n owner.node.weights.slice(0, index),\n before,\n position - owner.rect[axis] - fit.input.requirements.gap * index\n ),\n incoming[extent],\n ...fitSizes(\n owner.node.weights.slice(index + 1),\n after,\n owner.rect[axis] + owner.rect[extent] - position - incoming[extent] - fit.input.requirements.gap * after.length\n )\n ];\n}\n\nconst sum = (values: number[]) => values.reduce((total, value) => total + value, 0);\n\n/** Reuses the actual selected reservation before considering a different spatial offer. */\nexport function resolveSelectedPlacementPlan(\n input: Omit<AcquisitionInput, 'previous' | 'acquisition'> & {\n previous?: WorkspaceDragPreview;\n acquisition?: { rect: Rect; point: Point };\n clientOrigin: Rect;\n intent: WorkspaceDropIntent;\n }\n): WorkspacePlacementPlan | undefined {\n const prior = input.previous;\n if (blockedSelection(prior, input.intent) && !input.acquisition) return undefined;\n if (!selectedReservation(prior, input.source) || !spatialReservation(prior, input.plan)) return input.plan;\n const current = getGroupInsertion({ ...input, plan: prior });\n const next = getGroupInsertion(input);\n if (current && current.key === next?.key) return { ...input.plan, layout: prior.layout };\n if (!input.acquisition) return input.plan;\n const { rect, point } = input.acquisition;\n return fitAcquiredPlacement({\n ...input,\n previous: prior.layout,\n acquisition: {\n rect: { ...rect, x: rect.x - input.clientOrigin.x, y: rect.y - input.clientOrigin.y },\n point: { x: point.x - input.clientOrigin.x, y: point.y - input.clientOrigin.y }\n }\n });\n}\n\nfunction spatialReservation(preview: WorkspaceDragPreview, plan: WorkspacePlacementPlan) {\n return ['order', 'insert'].includes(preview.intent.kind) && ['insert', 'reorder'].includes(plan.kind);\n}\n\nfunction selectedReservation(\n preview: WorkspaceDragPreview | undefined,\n source: string[]\n): preview is Extract<WorkspaceDragPreview, { phase: 'detached' }> & { allocation: 'reserved' } {\n return (\n preview?.phase === 'detached' &&\n !preview.blocked &&\n preview.allocation === 'reserved' &&\n samePanelMembership(preview.source, source)\n );\n}\n\nfunction blockedSelection(preview: WorkspaceDragPreview | undefined, intent: WorkspaceDropIntent) {\n return preview?.phase === 'detached' && preview.blocked && matchesPlacementIntent(preview.intent, intent);\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { WorkspaceLayout } from '../model/layout.utils.js';
|
|
1
|
+
import type { WorkspaceLayout, WorkspaceSplit } from '../model/layout.utils.js';
|
|
2
2
|
import type { WorkspaceDestination } from '../model/operations.utils.js';
|
|
3
3
|
import type { WorkspaceLayoutProjector } from '../model/projection.utils.js';
|
|
4
|
-
import type { WorkspacePlacementPlan } from './planner.utils.js';
|
|
4
|
+
import type { WorkspacePlacementPlan, WorkspacePlacementPlanner } from './planner.utils.js';
|
|
5
|
+
import type { WorkspacePlacementSession } from './session.utils.js';
|
|
5
6
|
interface InsertionInput {
|
|
6
7
|
layout: WorkspaceLayout;
|
|
7
8
|
source: string[];
|
|
@@ -9,18 +10,23 @@ interface InsertionInput {
|
|
|
9
10
|
available: string[];
|
|
10
11
|
projectLayout?: WorkspaceLayoutProjector;
|
|
11
12
|
}
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
export interface GroupInsertionInputs {
|
|
14
|
+
readonly plan: Pick<WorkspacePlacementPlan, 'layout'>;
|
|
15
|
+
readonly source: string[];
|
|
16
|
+
readonly available: string[];
|
|
17
|
+
readonly projectLayout?: WorkspaceLayoutProjector;
|
|
18
|
+
readonly placementSession?: WorkspacePlacementSession;
|
|
19
|
+
readonly planPlacement?: WorkspacePlacementPlanner;
|
|
20
|
+
}
|
|
21
|
+
export interface GroupInsertion {
|
|
22
|
+
axis: WorkspaceSplit['axis'];
|
|
20
23
|
index: number;
|
|
21
24
|
members: string[];
|
|
22
|
-
previous
|
|
23
|
-
next
|
|
25
|
+
previous?: string[];
|
|
26
|
+
next?: string[];
|
|
24
27
|
key: string;
|
|
25
|
-
}
|
|
28
|
+
}
|
|
29
|
+
export declare function getGroupInsertion(input: GroupInsertionInputs): GroupInsertion | undefined;
|
|
30
|
+
export declare function planGroupInsertion(input: InsertionInput): WorkspacePlacementPlan | undefined;
|
|
31
|
+
export declare function computeGroupInsertion(input: GroupInsertionInputs): GroupInsertion | undefined;
|
|
26
32
|
export {};
|
|
@@ -1,48 +1,51 @@
|
|
|
1
1
|
import { getPanelIds as e, getSplitSide as t } from "../model/layout.utils.js";
|
|
2
2
|
import { createDetachedLayout as n, projectLayout as r } from "../model/operations.utils.js";
|
|
3
|
-
import { findDeepestProjectionCarrier as i,
|
|
3
|
+
import { findDeepestProjectionCarrier as i, rebaseProjectedSplit as a, sameProjectionShape as o } from "../model/projection.utils.js";
|
|
4
4
|
import { findWorkspaceRegion as s, placeRegion as c } from "./region.utils.js";
|
|
5
5
|
// src/workspace/utils/placement/group-insertion.utils.ts
|
|
6
6
|
function l(e) {
|
|
7
|
-
|
|
7
|
+
return e.placementSession && !e.planPlacement ? e.placementSession.getInsertion(e) : S(e);
|
|
8
|
+
}
|
|
9
|
+
function u(e) {
|
|
10
|
+
let t = h(e);
|
|
8
11
|
if (!t) return;
|
|
9
|
-
let n =
|
|
10
|
-
return n ?
|
|
12
|
+
let n = d(e, t);
|
|
13
|
+
return n ? f({
|
|
11
14
|
input: e,
|
|
12
15
|
context: t,
|
|
13
16
|
topology: n
|
|
14
17
|
}) : void 0;
|
|
15
18
|
}
|
|
16
|
-
function
|
|
17
|
-
let { peers:
|
|
19
|
+
function d(a, o) {
|
|
20
|
+
let { peers: s, insertionIndex: l, visible: u, root: d, axis: f } = o, p = s[Math.min(l, s.length - 1)], m = a.projectLayout ?? r, h = i(d, p.node, (e) => {
|
|
18
21
|
let t = n({
|
|
19
22
|
version: 1,
|
|
20
23
|
root: e,
|
|
21
24
|
closed: []
|
|
22
|
-
},
|
|
23
|
-
return
|
|
24
|
-
}),
|
|
25
|
-
if (!
|
|
26
|
-
let
|
|
27
|
-
target: e(
|
|
28
|
-
region:
|
|
29
|
-
position: t(
|
|
25
|
+
}, a.source);
|
|
26
|
+
return m(t, u).root;
|
|
27
|
+
}), g = h && b(d, h);
|
|
28
|
+
if (!g || !h) return;
|
|
29
|
+
let _ = l < s.length, v = {
|
|
30
|
+
target: e(h)[0],
|
|
31
|
+
region: g,
|
|
32
|
+
position: t(f, _ ? "before" : "after")
|
|
30
33
|
};
|
|
31
34
|
return c({
|
|
32
|
-
...
|
|
33
|
-
destination:
|
|
35
|
+
...a,
|
|
36
|
+
destination: v
|
|
34
37
|
});
|
|
35
38
|
}
|
|
36
|
-
function
|
|
37
|
-
let { owner: a, peers: o, visible: s, axis: c } = n, l = (t.projectLayout ?? r)(i.layout, s).root, u = t.source.filter((e) => s.includes(e)), d =
|
|
39
|
+
function f({ input: t, context: n, topology: i }) {
|
|
40
|
+
let { owner: a, peers: o, visible: s, axis: c } = n, l = (t.projectLayout ?? r)(i.layout, s).root, u = t.source.filter((e) => s.includes(e)), d = v(l, u);
|
|
38
41
|
if (!d || d.axis !== c || d.children.length !== o.length + 1) return;
|
|
39
|
-
let f =
|
|
42
|
+
let f = _({
|
|
40
43
|
branch: d,
|
|
41
44
|
peers: o,
|
|
42
45
|
moving: u
|
|
43
46
|
});
|
|
44
47
|
if (!f) return;
|
|
45
|
-
let p =
|
|
48
|
+
let p = x({
|
|
46
49
|
layout: i.layout,
|
|
47
50
|
branch: d,
|
|
48
51
|
weights: f,
|
|
@@ -51,18 +54,18 @@ function d({ input: t, context: n, topology: i }) {
|
|
|
51
54
|
if (p) return {
|
|
52
55
|
kind: "insert",
|
|
53
56
|
layout: p,
|
|
54
|
-
|
|
57
|
+
scope: {
|
|
55
58
|
kind: "rail",
|
|
56
59
|
members: [.../* @__PURE__ */ new Set([...e(a), ...u])]
|
|
57
60
|
}
|
|
58
61
|
};
|
|
59
62
|
}
|
|
60
|
-
function
|
|
63
|
+
function p(e) {
|
|
61
64
|
let { destination: t, layout: n } = e;
|
|
62
65
|
if (!t.region || t.position === "tab") return;
|
|
63
66
|
let i = e.available.filter((e) => !n.closed.includes(e)), a = (e.projectLayout ?? r)(n, i).root, o = s(a, t.region);
|
|
64
67
|
if (!a || !o) return;
|
|
65
|
-
let c = t.position === "left" || t.position === "right" ? "horizontal" : "vertical", l =
|
|
68
|
+
let c = t.position === "left" || t.position === "right" ? "horizontal" : "vertical", l = m({
|
|
66
69
|
root: a,
|
|
67
70
|
target: o,
|
|
68
71
|
key: t.region,
|
|
@@ -76,13 +79,13 @@ function f(e) {
|
|
|
76
79
|
owner: l
|
|
77
80
|
};
|
|
78
81
|
}
|
|
79
|
-
function
|
|
82
|
+
function m(e) {
|
|
80
83
|
if (e.target.type === "split" && e.target.axis === e.axis) return e.target;
|
|
81
84
|
let t = s(e.root, e.key.split(".").slice(0, -1).join("."));
|
|
82
85
|
return t?.type === "split" && t.axis === e.axis ? t : e.target.type === "split" ? e.target : void 0;
|
|
83
86
|
}
|
|
84
|
-
function
|
|
85
|
-
let r =
|
|
87
|
+
function h(t) {
|
|
88
|
+
let r = p(t);
|
|
86
89
|
if (!r) return;
|
|
87
90
|
let { owner: i, target: a, axis: o } = r, s = n({
|
|
88
91
|
version: 1,
|
|
@@ -90,16 +93,16 @@ function m(t) {
|
|
|
90
93
|
closed: []
|
|
91
94
|
}, t.source).root;
|
|
92
95
|
if (!s) return;
|
|
93
|
-
let c =
|
|
96
|
+
let c = g(s, o), l = new Set(e(a).filter((e) => !t.source.includes(e))), u = c.flatMap((t, n) => e(t.node).every((e) => l.has(e)) ? [n] : []);
|
|
94
97
|
if (!u.length) return;
|
|
95
98
|
let d = t.destination.position === "left" || t.destination.position === "top";
|
|
96
99
|
return {
|
|
97
100
|
...r,
|
|
98
101
|
peers: c,
|
|
99
|
-
|
|
102
|
+
insertionIndex: d ? u[0] : u.at(-1) + 1
|
|
100
103
|
};
|
|
101
104
|
}
|
|
102
|
-
function
|
|
105
|
+
function g(e, t) {
|
|
103
106
|
return e.type !== "split" || e.axis !== t ? [{
|
|
104
107
|
node: e,
|
|
105
108
|
weight: 1
|
|
@@ -108,43 +111,43 @@ function h(e, t) {
|
|
|
108
111
|
weight: e.weights[n]
|
|
109
112
|
}));
|
|
110
113
|
}
|
|
111
|
-
function
|
|
114
|
+
function _(e) {
|
|
112
115
|
let t = e.peers.reduce((e, t) => e + t.weight, 0) / e.peers.length, n = e.branch.children.map((n) => {
|
|
113
|
-
if (
|
|
114
|
-
let r = e.peers.findIndex((e) =>
|
|
116
|
+
if (y(n, e.moving)) return t;
|
|
117
|
+
let r = e.peers.findIndex((e) => o(e.node, n));
|
|
115
118
|
if (!(r < 0)) return e.peers[r].weight;
|
|
116
119
|
});
|
|
117
120
|
return n.every((e) => e !== void 0) ? n : void 0;
|
|
118
121
|
}
|
|
119
|
-
function
|
|
122
|
+
function v(e, t) {
|
|
120
123
|
if (e?.type === "split") {
|
|
121
|
-
if (e.children.some((e) => e.type === "group" && e.panels.length > 0 &&
|
|
124
|
+
if (e.children.some((e) => e.type === "group" && e.panels.length > 0 && y(e, t))) return e;
|
|
122
125
|
for (let n of e.children) {
|
|
123
|
-
let e =
|
|
126
|
+
let e = v(n, t);
|
|
124
127
|
if (e) return e;
|
|
125
128
|
}
|
|
126
129
|
}
|
|
127
130
|
}
|
|
128
|
-
function
|
|
131
|
+
function y(e, t) {
|
|
129
132
|
return e.type === "group" && e.panels.every((e) => t.includes(e));
|
|
130
133
|
}
|
|
131
|
-
function
|
|
134
|
+
function b(e, t, n = "root") {
|
|
132
135
|
if (e === t) return n;
|
|
133
136
|
if (e.type === "split") for (let [r, i] of e.children.entries()) {
|
|
134
|
-
let e =
|
|
137
|
+
let e = b(i, t, `${n}.${r}`);
|
|
135
138
|
if (e) return e;
|
|
136
139
|
}
|
|
137
140
|
}
|
|
138
|
-
function
|
|
139
|
-
let t =
|
|
141
|
+
function x(e) {
|
|
142
|
+
let t = a(e.layout, e.branch, e.weights, e.available);
|
|
140
143
|
if (t) return t;
|
|
141
144
|
let n = e.weights.reduce((e, t) => e + t, 0);
|
|
142
145
|
return e.branch.weights.every((t, r) => Math.abs(t - e.weights[r] / n) < 1e-10) ? e.layout : void 0;
|
|
143
146
|
}
|
|
144
|
-
function
|
|
145
|
-
let n = t.available.filter((e) => !t.plan.layout.closed.includes(e)), i = t.source.filter((e) => n.includes(e)), a =
|
|
147
|
+
function S(t) {
|
|
148
|
+
let n = t.available.filter((e) => !t.plan.layout.closed.includes(e)), i = t.source.filter((e) => n.includes(e)), a = v((t.projectLayout ?? r)(t.plan.layout, n).root, i);
|
|
146
149
|
if (!a) return;
|
|
147
|
-
let o = a.children.findIndex((e) =>
|
|
150
|
+
let o = a.children.findIndex((e) => y(e, i));
|
|
148
151
|
if (!(o < 0)) return {
|
|
149
152
|
axis: a.axis,
|
|
150
153
|
index: o,
|
|
@@ -154,18 +157,18 @@ function x(t) {
|
|
|
154
157
|
key: JSON.stringify([
|
|
155
158
|
a.axis,
|
|
156
159
|
o,
|
|
157
|
-
|
|
160
|
+
C(t.plan.layout.root),
|
|
158
161
|
t.plan.layout.closed
|
|
159
162
|
])
|
|
160
163
|
};
|
|
161
164
|
}
|
|
162
|
-
function
|
|
165
|
+
function C(e) {
|
|
163
166
|
return e ? e.type === "group" ? [
|
|
164
167
|
"group",
|
|
165
168
|
e.panels,
|
|
166
169
|
e.active
|
|
167
|
-
] : [e.axis, e.children.map(
|
|
170
|
+
] : [e.axis, e.children.map(C)] : null;
|
|
168
171
|
}
|
|
169
|
-
export {
|
|
172
|
+
export { S as computeGroupInsertion, l as getGroupInsertion, u as planGroupInsertion };
|
|
170
173
|
|
|
171
174
|
//# sourceMappingURL=group-insertion.utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"group-insertion.utils.js","names":["planGroupInsertion","context","insertionContext","input","topology","insertionTopology","sizeInsertion","donor","peers","slot","projectLayoutForCandidate","projectLayout","carrier","findDeepestProjectionCarrier","root","getProjectionSignature","residualLayout","createDetachedLayout","node","visible","key","nodeKey","before","destination","getPanelIds","getSplitSide","axis","placeRegion","projectedRoot","moving","id","branch","movingOwner","weights","insertedWeights","layout","insertionWeights","owner","insertionBasis","target","findWorkspaceRegion","insertionOwner","parent","basis","residual","insertionPeers","selected","matches","peer","index","incoming","sum","isMovingGroup","child","weight","found","rebased","rebaseProjectedSplit","total","describePlacementSlot","placementShape"],"sources":["../../../../src/workspace/utils/placement/group-insertion.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { getPanelIds, getSplitSide } from '../model/layout.utils.js';\nimport { createDetachedLayout, projectLayout } from '../model/operations.utils.js';\nimport {\n findDeepestProjectionCarrier,\n getProjectionSignature,\n rebaseProjectedSplit\n} from '../model/projection.utils.js';\nimport { findWorkspaceRegion, placeRegion } from './region.utils.js';\n\nimport type { WorkspaceLayout, WorkspaceNode, WorkspaceSplit } from '../model/layout.utils.js';\nimport type { WorkspaceDestination } from '../model/operations.utils.js';\nimport type { WorkspaceLayoutProjector } from '../model/projection.utils.js';\nimport type { WorkspacePlacementPlan } from './planner.utils.js';\n\ninterface InsertionInput {\n layout: WorkspaceLayout;\n source: string[];\n destination: WorkspaceDestination;\n available: string[];\n projectLayout?: WorkspaceLayoutProjector;\n}\n\nexport function planGroupInsertion(input: InsertionInput): WorkspacePlacementPlan | undefined {\n const context = insertionContext(input);\n if (!context) return undefined;\n const topology = insertionTopology(input, context);\n return topology ? sizeInsertion({ input, context, topology }) : undefined;\n}\n\nfunction insertionTopology(input: InsertionInput, context: NonNullable<ReturnType<typeof insertionContext>>) {\n const { peers, slot, visible, root, axis } = context;\n const donorIndex = Math.min(slot, peers.length - 1);\n const donor = peers[donorIndex]!;\n const projectLayoutForCandidate = input.projectLayout ?? projectLayout;\n const carrier = findDeepestProjectionCarrier(root, getProjectionSignature(donor.node), node => {\n const residualLayout = createDetachedLayout({ version: 1, root: node, closed: [] }, input.source);\n return projectLayoutForCandidate(residualLayout, visible).root;\n });\n const key = carrier && nodeKey(root, carrier);\n if (!key || !carrier) return undefined;\n const before = slot < peers.length;\n const destination: WorkspaceDestination = {\n target: getPanelIds(carrier)[0]!,\n region: key,\n position: getSplitSide(axis, before ? 'before' : 'after')\n };\n const topology = placeRegion({ ...input, destination });\n return topology;\n}\n\nfunction sizeInsertion({\n input,\n context,\n topology\n}: {\n input: InsertionInput;\n context: NonNullable<ReturnType<typeof insertionContext>>;\n topology: WorkspacePlacementPlan;\n}): WorkspacePlacementPlan | undefined {\n const { owner, peers, visible, axis } = context;\n const projectedRoot = (input.projectLayout ?? projectLayout)(topology.layout, visible).root;\n const moving = input.source.filter(id => visible.includes(id));\n const branch = movingOwner(projectedRoot, moving);\n if (!branch || branch.axis !== axis || branch.children.length !== peers.length + 1) return undefined;\n const weights = insertedWeights({\n branch,\n peers,\n moving\n });\n if (!weights) return undefined;\n const layout = insertionWeights({ layout: topology.layout, branch, weights, available: input.available });\n if (!layout) return undefined;\n return {\n kind: 'insert',\n layout,\n context: { kind: 'rail', members: [...new Set([...getPanelIds(owner), ...moving])] }\n };\n}\n\nfunction insertionBasis(input: InsertionInput) {\n const { destination, layout } = input;\n if (!destination.region || destination.position === 'tab') return undefined;\n const visible = input.available.filter(id => !layout.closed.includes(id));\n const root = (input.projectLayout ?? projectLayout)(layout, visible).root;\n const target = findWorkspaceRegion(root, destination.region);\n if (!root || !target) return undefined;\n const axis: WorkspaceSplit['axis'] =\n destination.position === 'left' || destination.position === 'right' ? 'horizontal' : 'vertical';\n const owner = insertionOwner({ root, target, key: destination.region, axis });\n if (!owner) return undefined;\n return {\n visible,\n root,\n target,\n axis,\n owner\n };\n}\n\nfunction insertionOwner(input: {\n root: WorkspaceNode;\n target: WorkspaceNode;\n key: string;\n axis: WorkspaceSplit['axis'];\n}) {\n if (input.target.type === 'split' && input.target.axis === input.axis) return input.target;\n const parent = findWorkspaceRegion(input.root, input.key.split('.').slice(0, -1).join('.'));\n if (parent?.type === 'split' && parent.axis === input.axis) return parent;\n return input.target.type === 'split' ? input.target : undefined;\n}\n\nfunction insertionContext(input: InsertionInput) {\n const basis = insertionBasis(input);\n if (!basis) return undefined;\n const { owner, target, axis } = basis;\n const residual = createDetachedLayout({ version: 1, root: owner, closed: [] }, input.source).root;\n if (!residual) return undefined;\n const peers = insertionPeers(residual, axis);\n const selected = new Set(getPanelIds(target).filter(id => !input.source.includes(id)));\n const matches = peers.flatMap((peer, index) => (getPanelIds(peer.node).every(id => selected.has(id)) ? [index] : []));\n if (!matches.length) return undefined;\n const before = input.destination.position === 'left' || input.destination.position === 'top';\n return { ...basis, peers, slot: before ? matches[0]! : matches.at(-1)! + 1 };\n}\n\nfunction insertionPeers(residual: WorkspaceNode, axis: WorkspaceSplit['axis']) {\n if (residual.type !== 'split' || residual.axis !== axis) return [{ node: residual, weight: 1 }];\n return residual.children.map((node, index) => ({ node, weight: residual.weights[index]! }));\n}\n\nfunction insertedWeights(input: {\n branch: WorkspaceSplit;\n peers: { node: WorkspaceNode; weight: number }[];\n moving: string[];\n}) {\n const incoming = input.peers.reduce((sum, peer) => sum + peer.weight, 0) / input.peers.length;\n const weights = input.branch.children.map(child => {\n if (isMovingGroup(child, input.moving)) return incoming;\n const index = input.peers.findIndex(peer => getProjectionSignature(peer.node) === getProjectionSignature(child));\n if (index < 0) return undefined;\n const weight = input.peers[index]!.weight;\n return weight;\n });\n return weights.every((weight): weight is number => weight !== undefined) ? weights : undefined;\n}\n\nfunction movingOwner(node: WorkspaceNode | null, moving: string[]): WorkspaceSplit | undefined {\n if (node?.type !== 'split') return undefined;\n if (node.children.some(child => child.type === 'group' && child.panels.length > 0 && isMovingGroup(child, moving)))\n return node;\n for (const child of node.children) {\n const found = movingOwner(child, moving);\n if (found) return found;\n }\n return undefined;\n}\n\nfunction isMovingGroup(node: WorkspaceNode, moving: string[]) {\n return node.type === 'group' && node.panels.every(id => moving.includes(id));\n}\n\nfunction nodeKey(node: WorkspaceNode, target: WorkspaceNode, key = 'root'): string | undefined {\n if (node === target) return key;\n if (node.type !== 'split') return undefined;\n for (const [index, child] of node.children.entries()) {\n const found = nodeKey(child, target, `${key}.${index}`);\n if (found) return found;\n }\n return undefined;\n}\n\nfunction insertionWeights(input: {\n layout: WorkspaceLayout;\n branch: WorkspaceSplit;\n weights: number[];\n available: string[];\n}) {\n const rebased = rebaseProjectedSplit(input.layout, input.branch, input.weights, input.available);\n if (rebased) return rebased;\n const total = input.weights.reduce((sum, weight) => sum + weight, 0);\n return input.branch.weights.every((weight, index) => Math.abs(weight - input.weights[index]! / total) < 1e-10)\n ? input.layout\n : undefined;\n}\n\nexport function describePlacementSlot(input: {\n plan: Pick<WorkspacePlacementPlan, 'layout'>;\n source: string[];\n available: string[];\n projectLayout?: WorkspaceLayoutProjector;\n}) {\n const visible = input.available.filter(id => !input.plan.layout.closed.includes(id));\n const moving = input.source.filter(id => visible.includes(id));\n const owner = movingOwner((input.projectLayout ?? projectLayout)(input.plan.layout, visible).root, moving);\n if (!owner) return undefined;\n const index = owner.children.findIndex(child => isMovingGroup(child, moving));\n if (index < 0) return undefined;\n return {\n axis: owner.axis,\n index,\n members: getPanelIds(owner).filter(id => !moving.includes(id)),\n previous: owner.children[index - 1] ? getPanelIds(owner.children[index - 1]!) : undefined,\n next: owner.children[index + 1] ? getPanelIds(owner.children[index + 1]!) : undefined,\n key: JSON.stringify([owner.axis, index, placementShape(input.plan.layout.root), input.plan.layout.closed])\n };\n}\n\nfunction placementShape(node: WorkspaceNode | null): unknown {\n if (!node) return null;\n return node.type === 'group' ? ['group', node.panels, node.active] : [node.axis, node.children.map(placementShape)];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"group-insertion.utils.js","names":["getGroupInsertion","input","computeGroupInsertion","planGroupInsertion","context","insertionContext","topology","insertionTopology","sizeInsertion","donor","peers","insertionIndex","projectLayoutForCandidate","projectLayout","carrier","findDeepestProjectionCarrier","root","residualLayout","createDetachedLayout","node","visible","key","nodeKey","before","destination","getPanelIds","getSplitSide","axis","placeRegion","projectedRoot","moving","id","branch","movingOwner","weights","insertedWeights","layout","insertionWeights","owner","insertionBasis","target","findWorkspaceRegion","insertionOwner","parent","basis","residual","insertionPeers","selected","matches","peer","index","incoming","sum","isMovingGroup","child","sameProjectionShape","weight","found","rebased","rebaseProjectedSplit","total","placementShape"],"sources":["../../../../src/workspace/utils/placement/group-insertion.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { getPanelIds, getSplitSide } from '../model/layout.utils.js';\nimport { createDetachedLayout, projectLayout } from '../model/operations.utils.js';\nimport { findDeepestProjectionCarrier, rebaseProjectedSplit, sameProjectionShape } from '../model/projection.utils.js';\nimport { findWorkspaceRegion, placeRegion } from './region.utils.js';\n\nimport type { WorkspaceLayout, WorkspaceNode, WorkspaceSplit } from '../model/layout.utils.js';\nimport type { WorkspaceDestination } from '../model/operations.utils.js';\nimport type { WorkspaceLayoutProjector } from '../model/projection.utils.js';\nimport type { WorkspacePlacementPlan, WorkspacePlacementPlanner } from './planner.utils.js';\nimport type { WorkspacePlacementSession } from './session.utils.js';\n\ninterface InsertionInput {\n layout: WorkspaceLayout;\n source: string[];\n destination: WorkspaceDestination;\n available: string[];\n projectLayout?: WorkspaceLayoutProjector;\n}\n\nexport interface GroupInsertionInputs {\n readonly plan: Pick<WorkspacePlacementPlan, 'layout'>;\n readonly source: string[];\n readonly available: string[];\n readonly projectLayout?: WorkspaceLayoutProjector;\n readonly placementSession?: WorkspacePlacementSession;\n readonly planPlacement?: WorkspacePlacementPlanner;\n}\n\nexport interface GroupInsertion {\n axis: WorkspaceSplit['axis'];\n index: number;\n members: string[];\n previous?: string[];\n next?: string[];\n key: string;\n}\n\nexport function getGroupInsertion(input: GroupInsertionInputs): GroupInsertion | undefined {\n return input.placementSession && !input.planPlacement\n ? input.placementSession.getInsertion(input)\n : computeGroupInsertion(input);\n}\n\nexport function planGroupInsertion(input: InsertionInput): WorkspacePlacementPlan | undefined {\n const context = insertionContext(input);\n if (!context) return undefined;\n const topology = insertionTopology(input, context);\n return topology ? sizeInsertion({ input, context, topology }) : undefined;\n}\n\nfunction insertionTopology(input: InsertionInput, context: NonNullable<ReturnType<typeof insertionContext>>) {\n const { peers, insertionIndex, visible, root, axis } = context;\n const donorIndex = Math.min(insertionIndex, peers.length - 1);\n const donor = peers[donorIndex]!;\n const projectLayoutForCandidate = input.projectLayout ?? projectLayout;\n const carrier = findDeepestProjectionCarrier(root, donor.node, node => {\n const residualLayout = createDetachedLayout({ version: 1, root: node, closed: [] }, input.source);\n return projectLayoutForCandidate(residualLayout, visible).root;\n });\n const key = carrier && nodeKey(root, carrier);\n if (!key || !carrier) return undefined;\n const before = insertionIndex < peers.length;\n const destination: WorkspaceDestination = {\n target: getPanelIds(carrier)[0]!,\n region: key,\n position: getSplitSide(axis, before ? 'before' : 'after')\n };\n const topology = placeRegion({ ...input, destination });\n return topology;\n}\n\nfunction sizeInsertion({\n input,\n context,\n topology\n}: {\n input: InsertionInput;\n context: NonNullable<ReturnType<typeof insertionContext>>;\n topology: WorkspacePlacementPlan;\n}): WorkspacePlacementPlan | undefined {\n const { owner, peers, visible, axis } = context;\n const projectedRoot = (input.projectLayout ?? projectLayout)(topology.layout, visible).root;\n const moving = input.source.filter(id => visible.includes(id));\n const branch = movingOwner(projectedRoot, moving);\n if (!branch || branch.axis !== axis || branch.children.length !== peers.length + 1) return undefined;\n const weights = insertedWeights({\n branch,\n peers,\n moving\n });\n if (!weights) return undefined;\n const layout = insertionWeights({ layout: topology.layout, branch, weights, available: input.available });\n if (!layout) return undefined;\n return {\n kind: 'insert',\n layout,\n scope: { kind: 'rail', members: [...new Set([...getPanelIds(owner), ...moving])] }\n };\n}\n\nfunction insertionBasis(input: InsertionInput) {\n const { destination, layout } = input;\n if (!destination.region || destination.position === 'tab') return undefined;\n const visible = input.available.filter(id => !layout.closed.includes(id));\n const root = (input.projectLayout ?? projectLayout)(layout, visible).root;\n const target = findWorkspaceRegion(root, destination.region);\n if (!root || !target) return undefined;\n const axis: WorkspaceSplit['axis'] =\n destination.position === 'left' || destination.position === 'right' ? 'horizontal' : 'vertical';\n const owner = insertionOwner({ root, target, key: destination.region, axis });\n if (!owner) return undefined;\n return {\n visible,\n root,\n target,\n axis,\n owner\n };\n}\n\nfunction insertionOwner(input: {\n root: WorkspaceNode;\n target: WorkspaceNode;\n key: string;\n axis: WorkspaceSplit['axis'];\n}) {\n if (input.target.type === 'split' && input.target.axis === input.axis) return input.target;\n const parent = findWorkspaceRegion(input.root, input.key.split('.').slice(0, -1).join('.'));\n if (parent?.type === 'split' && parent.axis === input.axis) return parent;\n return input.target.type === 'split' ? input.target : undefined;\n}\n\nfunction insertionContext(input: InsertionInput) {\n const basis = insertionBasis(input);\n if (!basis) return undefined;\n const { owner, target, axis } = basis;\n const residual = createDetachedLayout({ version: 1, root: owner, closed: [] }, input.source).root;\n if (!residual) return undefined;\n const peers = insertionPeers(residual, axis);\n const selected = new Set(getPanelIds(target).filter(id => !input.source.includes(id)));\n const matches = peers.flatMap((peer, index) => (getPanelIds(peer.node).every(id => selected.has(id)) ? [index] : []));\n if (!matches.length) return undefined;\n const before = input.destination.position === 'left' || input.destination.position === 'top';\n return { ...basis, peers, insertionIndex: before ? matches[0]! : matches.at(-1)! + 1 };\n}\n\nfunction insertionPeers(residual: WorkspaceNode, axis: WorkspaceSplit['axis']) {\n if (residual.type !== 'split' || residual.axis !== axis) return [{ node: residual, weight: 1 }];\n return residual.children.map((node, index) => ({ node, weight: residual.weights[index]! }));\n}\n\nfunction insertedWeights(input: {\n branch: WorkspaceSplit;\n peers: { node: WorkspaceNode; weight: number }[];\n moving: string[];\n}) {\n const incoming = input.peers.reduce((sum, peer) => sum + peer.weight, 0) / input.peers.length;\n const weights = input.branch.children.map(child => {\n if (isMovingGroup(child, input.moving)) return incoming;\n const index = input.peers.findIndex(peer => sameProjectionShape(peer.node, child));\n if (index < 0) return undefined;\n const weight = input.peers[index]!.weight;\n return weight;\n });\n return weights.every((weight): weight is number => weight !== undefined) ? weights : undefined;\n}\n\nfunction movingOwner(node: WorkspaceNode | null, moving: string[]): WorkspaceSplit | undefined {\n if (node?.type !== 'split') return undefined;\n if (node.children.some(child => child.type === 'group' && child.panels.length > 0 && isMovingGroup(child, moving)))\n return node;\n for (const child of node.children) {\n const found = movingOwner(child, moving);\n if (found) return found;\n }\n return undefined;\n}\n\nfunction isMovingGroup(node: WorkspaceNode, moving: string[]) {\n return node.type === 'group' && node.panels.every(id => moving.includes(id));\n}\n\nfunction nodeKey(node: WorkspaceNode, target: WorkspaceNode, key = 'root'): string | undefined {\n if (node === target) return key;\n if (node.type !== 'split') return undefined;\n for (const [index, child] of node.children.entries()) {\n const found = nodeKey(child, target, `${key}.${index}`);\n if (found) return found;\n }\n return undefined;\n}\n\nfunction insertionWeights(input: {\n layout: WorkspaceLayout;\n branch: WorkspaceSplit;\n weights: number[];\n available: string[];\n}) {\n const rebased = rebaseProjectedSplit(input.layout, input.branch, input.weights, input.available);\n if (rebased) return rebased;\n const total = input.weights.reduce((sum, weight) => sum + weight, 0);\n return input.branch.weights.every((weight, index) => Math.abs(weight - input.weights[index]! / total) < 1e-10)\n ? input.layout\n : undefined;\n}\n\nexport function computeGroupInsertion(input: GroupInsertionInputs): GroupInsertion | undefined {\n const visible = input.available.filter(id => !input.plan.layout.closed.includes(id));\n const moving = input.source.filter(id => visible.includes(id));\n const owner = movingOwner((input.projectLayout ?? projectLayout)(input.plan.layout, visible).root, moving);\n if (!owner) return undefined;\n const index = owner.children.findIndex(child => isMovingGroup(child, moving));\n if (index < 0) return undefined;\n return {\n axis: owner.axis,\n index,\n members: getPanelIds(owner).filter(id => !moving.includes(id)),\n previous: owner.children[index - 1] ? getPanelIds(owner.children[index - 1]!) : undefined,\n next: owner.children[index + 1] ? getPanelIds(owner.children[index + 1]!) : undefined,\n key: JSON.stringify([owner.axis, index, placementShape(input.plan.layout.root), input.plan.layout.closed])\n };\n}\n\nfunction placementShape(node: WorkspaceNode | null): unknown {\n if (!node) return null;\n return node.type === 'group' ? ['group', node.panels, node.active] : [node.axis, node.children.map(placementShape)];\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { WorkspaceLayout } from '../model/layout.utils.js';
|
|
2
2
|
import type { WorkspaceDestination } from '../model/operations.utils.js';
|
|
3
3
|
import type { WorkspaceLayoutProjector } from '../model/projection.utils.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type { WorkspacePlacementScope } from './scope.utils.js';
|
|
5
|
+
import type { WorkspacePlacementSession } from './session.utils.js';
|
|
5
6
|
export interface WorkspacePlacementPlan {
|
|
6
7
|
kind: 'reorder' | 'split' | 'tab' | 'insert';
|
|
7
|
-
|
|
8
|
+
scope?: WorkspacePlacementScope;
|
|
8
9
|
layout: WorkspaceLayout;
|
|
9
10
|
}
|
|
10
11
|
interface PlacementInput {
|
|
@@ -18,5 +19,15 @@ interface PlacementInput {
|
|
|
18
19
|
export type WorkspacePlacementPlanner = (input: PlacementInput) => WorkspacePlacementPlan | undefined;
|
|
19
20
|
/** Requires an immutable current layout; projection callbacks are never retained. */
|
|
20
21
|
export declare function createWorkspacePlacementPlanner(): WorkspacePlacementPlanner;
|
|
22
|
+
interface WorkspacePlanningContext {
|
|
23
|
+
currentLayout: WorkspaceLayout;
|
|
24
|
+
source: string[];
|
|
25
|
+
available: string[];
|
|
26
|
+
projectLayout?: WorkspaceLayoutProjector;
|
|
27
|
+
planPlacement?: WorkspacePlacementPlanner;
|
|
28
|
+
placementSession?: WorkspacePlacementSession;
|
|
29
|
+
}
|
|
30
|
+
/** Supplied planners keep their ordinary path; component gestures use their explicit session. */
|
|
31
|
+
export declare function resolvePlacementPlan(context: WorkspacePlanningContext, destination: WorkspaceDestination, operation: PlacementInput['operation']): WorkspacePlacementPlan | undefined;
|
|
21
32
|
export declare function planWorkspacePlacement(input: PlacementInput): WorkspacePlacementPlan | undefined;
|
|
22
33
|
export {};
|