@nvidia-elements/core 2.22.5 → 2.23.1
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 +15 -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/bundle.d.ts +4 -0
- package/dist/bundles/index.d.ts +357 -1
- package/dist/bundles/index.js +14 -14
- 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 +6 -6
- package/dist/combobox/combobox2.js +1 -1
- package/dist/copy-button/copy-button2.js +1 -1
- package/dist/custom-elements-jsx.d.ts +189 -0
- package/dist/custom-elements-vue.d.ts +189 -0
- package/dist/custom-elements.json +6561 -339
- package/dist/data.html.json +133 -0
- package/dist/date/date2.js +6 -6
- package/dist/datetime/datetime2.js +6 -6
- 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/forms/utils/layout.d.ts +0 -1
- package/dist/forms/utils/layout.js.map +1 -1
- package/dist/forms/utils/states.d.ts +0 -1
- package/dist/forms/utils/states.js.map +1 -1
- package/dist/gauge/gauge2.js +1 -1
- package/dist/ghost/define.d.ts +6 -0
- package/dist/ghost/define.js +6 -0
- package/dist/ghost/define.js.map +1 -0
- package/dist/ghost/ghost.d.ts +27 -0
- package/dist/ghost/ghost.examples.js +5 -0
- package/dist/ghost/ghost.examples.js.map +1 -0
- package/dist/ghost/ghost.examples.json +37 -0
- package/dist/ghost/ghost.js +5 -0
- package/dist/ghost/ghost.js.map +1 -0
- package/dist/ghost/ghost2.js +28 -0
- package/dist/ghost/ghost2.js.map +1 -0
- package/dist/ghost/index.d.ts +1 -0
- package/dist/ghost/index.js +1 -0
- 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 +2 -2
- package/dist/icon-button/icon-button2.js +1 -1
- package/dist/iframe/iframe2.js +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/input/input-group2.js +1 -1
- package/dist/input/input2.js +1 -1
- package/dist/internal/controllers/keynav-spatial.controller.d.ts +0 -1
- package/dist/internal/controllers/keynav-spatial.controller.js.map +1 -1
- package/dist/internal/controllers/type-native-popover.utils.d.ts +0 -1
- package/dist/internal/controllers/type-native-popover.utils.js.map +1 -1
- package/dist/internal/index.d.ts +0 -1
- package/dist/internal/index.js +116 -128
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/types/index.d.ts +37 -3
- package/dist/internal/types/index.js.map +1 -1
- package/dist/internal/utils/audit-logs.d.ts +0 -1
- package/dist/internal/utils/audit-logs.js.map +1 -1
- package/dist/internal/utils/dom.d.ts +0 -5
- package/dist/internal/utils/dom.js +30 -46
- package/dist/internal/utils/dom.js.map +1 -1
- package/dist/internal/utils/events.d.ts +0 -1
- package/dist/internal/utils/events.js +4 -7
- package/dist/internal/utils/events.js.map +1 -1
- package/dist/internal/utils/keynav.d.ts +0 -1
- package/dist/internal/utils/keynav.js +2 -5
- package/dist/internal/utils/keynav.js.map +1 -1
- package/dist/internal/utils/objects.d.ts +0 -2
- package/dist/internal/utils/objects.js +2 -8
- package/dist/internal/utils/objects.js.map +1 -1
- package/dist/joystick/joystick2.js +5 -5
- 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 +6 -6
- 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 +6 -6
- package/dist/preferences-input/preferences-input2.js +5 -5
- 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 +5 -5
- package/dist/search/search2.js +6 -6
- 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 +6 -6
- 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 +5 -5
- package/dist/textarea/textarea2.js +1 -1
- package/dist/time/time2.js +6 -6
- 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 +6 -6
- package/dist/workspace/controllers/workspace-command.controller.d.ts +34 -0
- package/dist/workspace/controllers/workspace-command.controller.js +87 -0
- package/dist/workspace/controllers/workspace-command.controller.js.map +1 -0
- package/dist/workspace/controllers/workspace-composition.controller.d.ts +54 -0
- package/dist/workspace/controllers/workspace-composition.controller.js +169 -0
- package/dist/workspace/controllers/workspace-composition.controller.js.map +1 -0
- package/dist/workspace/controllers/workspace-fullscreen.controller.d.ts +25 -0
- package/dist/workspace/controllers/workspace-fullscreen.controller.js +84 -0
- package/dist/workspace/controllers/workspace-fullscreen.controller.js.map +1 -0
- package/dist/workspace/controllers/workspace-measurement.controller.d.ts +19 -0
- package/dist/workspace/controllers/workspace-measurement.controller.js +188 -0
- package/dist/workspace/controllers/workspace-measurement.controller.js.map +1 -0
- package/dist/workspace/controllers/workspace-rearrange.controller.d.ts +40 -0
- package/dist/workspace/controllers/workspace-rearrange.controller.js +385 -0
- package/dist/workspace/controllers/workspace-rearrange.controller.js.map +1 -0
- package/dist/workspace/controllers/workspace-resize.controller.d.ts +43 -0
- package/dist/workspace/controllers/workspace-resize.controller.js +168 -0
- package/dist/workspace/controllers/workspace-resize.controller.js.map +1 -0
- package/dist/workspace/controllers/workspace-restoration.controller.d.ts +24 -0
- package/dist/workspace/controllers/workspace-restoration.controller.js +193 -0
- package/dist/workspace/controllers/workspace-restoration.controller.js.map +1 -0
- package/dist/workspace/define.d.ts +10 -0
- package/dist/workspace/define.js +9 -0
- package/dist/workspace/define.js.map +1 -0
- package/dist/workspace/index.d.ts +11 -0
- package/dist/workspace/index.js +6 -0
- package/dist/workspace/panel/panel.d.ts +48 -0
- package/dist/workspace/panel/panel.js +5 -0
- package/dist/workspace/panel/panel.js.map +1 -0
- package/dist/workspace/panel/panel2.js +53 -0
- package/dist/workspace/panel/panel2.js.map +1 -0
- package/dist/workspace/panel-content/panel-content.d.ts +20 -0
- package/dist/workspace/panel-content/panel-content.js +5 -0
- package/dist/workspace/panel-content/panel-content.js.map +1 -0
- package/dist/workspace/panel-content/panel-content2.js +22 -0
- package/dist/workspace/panel-content/panel-content2.js.map +1 -0
- package/dist/workspace/panel-footer/panel-footer.d.ts +24 -0
- package/dist/workspace/panel-footer/panel-footer.js +5 -0
- package/dist/workspace/panel-footer/panel-footer.js.map +1 -0
- package/dist/workspace/panel-footer/panel-footer2.js +28 -0
- package/dist/workspace/panel-footer/panel-footer2.js.map +1 -0
- package/dist/workspace/panel-header/panel-header.d.ts +61 -0
- package/dist/workspace/panel-header/panel-header.js +5 -0
- package/dist/workspace/panel-header/panel-header.js.map +1 -0
- package/dist/workspace/panel-header/panel-header2.js +102 -0
- package/dist/workspace/panel-header/panel-header2.js.map +1 -0
- package/dist/workspace/utils/evaluation.utils.d.ts +83 -0
- package/dist/workspace/utils/evaluation.utils.js +294 -0
- package/dist/workspace/utils/evaluation.utils.js.map +1 -0
- package/dist/workspace/utils/geometry/allocation.utils.d.ts +40 -0
- package/dist/workspace/utils/geometry/allocation.utils.js +73 -0
- package/dist/workspace/utils/geometry/allocation.utils.js.map +1 -0
- package/dist/workspace/utils/geometry/partition.utils.d.ts +10 -0
- package/dist/workspace/utils/geometry/partition.utils.js +40 -0
- package/dist/workspace/utils/geometry/partition.utils.js.map +1 -0
- package/dist/workspace/utils/geometry/sizing.utils.d.ts +35 -0
- package/dist/workspace/utils/geometry/sizing.utils.js +42 -0
- package/dist/workspace/utils/geometry/sizing.utils.js.map +1 -0
- package/dist/workspace/utils/interaction/boundary.utils.d.ts +40 -0
- package/dist/workspace/utils/interaction/boundary.utils.js +91 -0
- package/dist/workspace/utils/interaction/boundary.utils.js.map +1 -0
- package/dist/workspace/utils/interaction/command.utils.d.ts +74 -0
- package/dist/workspace/utils/interaction/command.utils.js +189 -0
- package/dist/workspace/utils/interaction/command.utils.js.map +1 -0
- package/dist/workspace/utils/interaction/drag-preview.utils.d.ts +79 -0
- package/dist/workspace/utils/interaction/drag-preview.utils.js +16 -0
- package/dist/workspace/utils/interaction/drag-preview.utils.js.map +1 -0
- package/dist/workspace/utils/interaction/insertion-offers.utils.d.ts +58 -0
- package/dist/workspace/utils/interaction/insertion-offers.utils.js +259 -0
- package/dist/workspace/utils/interaction/insertion-offers.utils.js.map +1 -0
- package/dist/workspace/utils/interaction/placement-decision.utils.d.ts +55 -0
- package/dist/workspace/utils/interaction/placement-decision.utils.js +242 -0
- package/dist/workspace/utils/interaction/placement-decision.utils.js.map +1 -0
- package/dist/workspace/utils/interaction/resize-input.utils.d.ts +1 -0
- package/dist/workspace/utils/interaction/resize-input.utils.js +17 -0
- package/dist/workspace/utils/interaction/resize-input.utils.js.map +1 -0
- package/dist/workspace/utils/model/layout.utils.d.ts +22 -0
- package/dist/workspace/utils/model/layout.utils.js +41 -0
- package/dist/workspace/utils/model/layout.utils.js.map +1 -0
- package/dist/workspace/utils/model/membership.utils.d.ts +14 -0
- package/dist/workspace/utils/model/membership.utils.js +17 -0
- package/dist/workspace/utils/model/membership.utils.js.map +1 -0
- package/dist/workspace/utils/model/operations.utils.d.ts +31 -0
- package/dist/workspace/utils/model/operations.utils.js +178 -0
- package/dist/workspace/utils/model/operations.utils.js.map +1 -0
- package/dist/workspace/utils/model/projection.utils.d.ts +7 -0
- package/dist/workspace/utils/model/projection.utils.js +87 -0
- package/dist/workspace/utils/model/projection.utils.js.map +1 -0
- package/dist/workspace/utils/model/value.utils.d.ts +5 -0
- package/dist/workspace/utils/model/value.utils.js +68 -0
- package/dist/workspace/utils/model/value.utils.js.map +1 -0
- package/dist/workspace/utils/placement/acquisition-sizing.utils.d.ts +32 -0
- package/dist/workspace/utils/placement/acquisition-sizing.utils.js +152 -0
- package/dist/workspace/utils/placement/acquisition-sizing.utils.js.map +1 -0
- package/dist/workspace/utils/placement/context.utils.d.ts +36 -0
- package/dist/workspace/utils/placement/context.utils.js +135 -0
- package/dist/workspace/utils/placement/context.utils.js.map +1 -0
- package/dist/workspace/utils/placement/group-insertion.utils.d.ts +26 -0
- package/dist/workspace/utils/placement/group-insertion.utils.js +171 -0
- package/dist/workspace/utils/placement/group-insertion.utils.js.map +1 -0
- package/dist/workspace/utils/placement/origin.utils.d.ts +13 -0
- package/dist/workspace/utils/placement/origin.utils.js +49 -0
- package/dist/workspace/utils/placement/origin.utils.js.map +1 -0
- package/dist/workspace/utils/placement/planner.utils.d.ts +22 -0
- package/dist/workspace/utils/placement/planner.utils.js +184 -0
- package/dist/workspace/utils/placement/planner.utils.js.map +1 -0
- package/dist/workspace/utils/placement/preparation.utils.d.ts +28 -0
- package/dist/workspace/utils/placement/preparation.utils.js +140 -0
- package/dist/workspace/utils/placement/preparation.utils.js.map +1 -0
- package/dist/workspace/utils/placement/region.utils.d.ts +15 -0
- package/dist/workspace/utils/placement/region.utils.js +111 -0
- package/dist/workspace/utils/placement/region.utils.js.map +1 -0
- package/dist/workspace/utils/placement/split-sizing.utils.d.ts +18 -0
- package/dist/workspace/utils/placement/split-sizing.utils.js +108 -0
- package/dist/workspace/utils/placement/split-sizing.utils.js.map +1 -0
- package/dist/workspace/utils/presentation/composition.utils.d.ts +17 -0
- package/dist/workspace/utils/presentation/composition.utils.js +95 -0
- package/dist/workspace/utils/presentation/composition.utils.js.map +1 -0
- package/dist/workspace/utils/presentation/groups.utils.d.ts +91 -0
- package/dist/workspace/utils/presentation/groups.utils.js +169 -0
- package/dist/workspace/utils/presentation/groups.utils.js.map +1 -0
- package/dist/workspace/utils/presentation/header-configuration.utils.d.ts +11 -0
- package/dist/workspace/utils/presentation/header-configuration.utils.js +7 -0
- package/dist/workspace/utils/presentation/header-configuration.utils.js.map +1 -0
- package/dist/workspace/utils/presentation/measurements.utils.d.ts +21 -0
- package/dist/workspace/utils/presentation/measurements.utils.js +28 -0
- package/dist/workspace/utils/presentation/measurements.utils.js.map +1 -0
- package/dist/workspace/utils/presentation/offers.utils.d.ts +43 -0
- package/dist/workspace/utils/presentation/offers.utils.js +137 -0
- package/dist/workspace/utils/presentation/offers.utils.js.map +1 -0
- package/dist/workspace/utils/presentation/preview.utils.d.ts +6 -0
- package/dist/workspace/utils/presentation/preview.utils.js +36 -0
- package/dist/workspace/utils/presentation/preview.utils.js.map +1 -0
- package/dist/workspace/workspace.d.ts +103 -0
- package/dist/workspace/workspace.examples.js +5 -0
- package/dist/workspace/workspace.examples.js.map +1 -0
- package/dist/workspace/workspace.examples.json +133 -0
- package/dist/workspace/workspace.js +5 -0
- package/dist/workspace/workspace.js.map +1 -0
- package/dist/workspace/workspace.types.d.ts +3 -0
- package/dist/workspace/workspace2.js +518 -0
- package/dist/workspace/workspace2.js.map +1 -0
- package/package.json +27 -3
- package/dist/internal/utils/supports.d.ts +0 -3
- package/dist/internal/utils/supports.js +0 -13
- package/dist/internal/utils/supports.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measurements.utils.js","names":["measurementProperties","sameWorkspaceMeasurements","previous","property","current","samePanelMeasurements","id","before","after"],"sources":["../../../../src/workspace/utils/presentation/measurements.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nexport interface WorkspacePanelMeasurements {\n suffixWidth: number;\n footerHeight: number;\n}\n\nexport interface WorkspaceMeasurements {\n gap: number;\n panels?: Record<string, WorkspacePanelMeasurements>;\n headerHeight: number;\n gripWidth: number;\n actionWidth: number;\n groupActionWidth?: number;\n tabWidth: number;\n tabMinWidth: number;\n width: number;\n height: number;\n}\n\nexport interface WorkspaceMeasurementChange {\n readonly measurements: WorkspaceMeasurements;\n readonly spaceChanged: boolean;\n}\n\nconst measurementProperties = [\n 'gap',\n 'headerHeight',\n 'gripWidth',\n 'actionWidth',\n 'groupActionWidth',\n 'tabWidth',\n 'tabMinWidth',\n 'width',\n 'height'\n] as const;\n\nexport function sameWorkspaceMeasurements(previous: WorkspaceMeasurements | undefined, current: WorkspaceMeasurements) {\n return (\n previous !== undefined &&\n measurementProperties.every(property => previous[property] === current[property]) &&\n samePanelMeasurements(previous.panels, current.panels)\n );\n}\n\nfunction samePanelMeasurements(previous: WorkspaceMeasurements['panels'], current: WorkspaceMeasurements['panels']) {\n if (previous === current) return true;\n if (!previous || !current) return false;\n for (const id in previous) {\n const before = previous[id]!;\n const after = current[id];\n if (!after || before.suffixWidth !== after.suffixWidth || before.footerHeight !== after.footerHeight) {\n return false;\n }\n }\n for (const id in current) {\n if (!Object.hasOwn(previous, id)) return false;\n }\n return true;\n}\n"],"mappings":";AA0BA,IAAMA,IAAwB;CAC5B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAgBC,EAA0B,GAA6C,GAAgC;CACrH,OACEC,MAAa,KAAA,KACbF,EAAsB,OAAM,MAAYE,EAASC,OAAcC,EAAQD,EAAS,KAChFE,EAAsBH,EAAS,QAAQE,EAAQ,MAAM;AAEzD;AAEA,SAASC,EAAsB,GAA2C,GAA0C;CAClH,IAAIH,MAAaE,GAAS,OAAO;CACjC,IAAI,CAACF,KAAY,CAACE,GAAS,OAAO;CAClC,KAAK,IAAME,KAAMJ,GAAU;EACzB,IAAMK,IAASL,EAASI,IAClBE,IAAQJ,EAAQE;EACtB,IAAI,CAACE,KAASD,EAAO,gBAAgBC,EAAM,eAAeD,EAAO,iBAAiBC,EAAM,cACtF,OAAO;CAEX;CACA,KAAK,IAAMF,KAAMF,GACf,IAAI,CAAC,OAAO,OAAOF,GAAUI,CAAE,GAAG,OAAO;CAE3C,OAAO;AACT"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Rect } from '@nvidia-elements/core/internal';
|
|
2
|
+
import type { WorkspacePlacedRegion } from '../geometry/allocation.utils.js';
|
|
3
|
+
import type { WorkspaceDragAllocation } from '../interaction/drag-preview.utils.js';
|
|
4
|
+
import type { WorkspaceDestination } from '../model/operations.utils.js';
|
|
5
|
+
import type { WorkspacePlacementPlan } from '../placement/planner.utils.js';
|
|
6
|
+
type WorkspaceSeamSide = 'left' | 'right' | 'top' | 'bottom';
|
|
7
|
+
export interface WorkspaceSeamPreview {
|
|
8
|
+
kind: 'split' | 'insert';
|
|
9
|
+
edges: {
|
|
10
|
+
side: WorkspaceSeamSide;
|
|
11
|
+
offset: number;
|
|
12
|
+
fraction: number;
|
|
13
|
+
}[];
|
|
14
|
+
}
|
|
15
|
+
/** Separates a group split's intended half from its constrained committed allocation. */
|
|
16
|
+
export declare function getOfferPresentation(input: {
|
|
17
|
+
plan: WorkspacePlacementPlan;
|
|
18
|
+
regions: WorkspacePlacedRegion[];
|
|
19
|
+
sourceKey: string;
|
|
20
|
+
sourceRect: Rect;
|
|
21
|
+
cue: Rect;
|
|
22
|
+
bounds: Rect;
|
|
23
|
+
destination: WorkspaceDestination;
|
|
24
|
+
feasible: boolean;
|
|
25
|
+
split?: {
|
|
26
|
+
source: string[];
|
|
27
|
+
regions: WorkspacePlacedRegion[];
|
|
28
|
+
groups: {
|
|
29
|
+
panels: {
|
|
30
|
+
id: string;
|
|
31
|
+
}[];
|
|
32
|
+
rect: Rect;
|
|
33
|
+
}[];
|
|
34
|
+
};
|
|
35
|
+
client(rect: Rect): Rect;
|
|
36
|
+
}): {
|
|
37
|
+
cue: Rect;
|
|
38
|
+
seams: WorkspaceSeamPreview | undefined;
|
|
39
|
+
context: import("../placement/context.utils.js").WorkspacePlacementContext | undefined;
|
|
40
|
+
};
|
|
41
|
+
/** Chooses live reservation separately from the unchanged candidate and commitment. */
|
|
42
|
+
export declare function getOfferAllocation(plan: WorkspacePlacementPlan, feasible: boolean): WorkspaceDragAllocation;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { clipCue as e } from "../interaction/drag-preview.utils.js";
|
|
2
|
+
import { getAffectedSplitContext as t } from "../placement/context.utils.js";
|
|
3
|
+
// src/workspace/utils/presentation/offers.utils.ts
|
|
4
|
+
function n(n) {
|
|
5
|
+
let r = n.split?.groups.find((e) => e.panels.some((e) => e.id === n.destination.target)), o = r && n.destination.position !== "tab" ? a(n.client(r.rect), n.destination.position) : void 0, s = e(o?.cue ?? n.cue, n.bounds);
|
|
6
|
+
return {
|
|
7
|
+
cue: s,
|
|
8
|
+
seams: i(n, o, s),
|
|
9
|
+
context: r && n.split ? t({
|
|
10
|
+
baseline: n.split.regions,
|
|
11
|
+
achieved: n.regions,
|
|
12
|
+
source: n.split.source,
|
|
13
|
+
recipient: r.panels.map((e) => e.id)
|
|
14
|
+
}) : n.plan.context
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function r(e, t) {
|
|
18
|
+
return (e.kind === "reorder" || e.kind === "tab" || e.kind === "insert") && t ? {
|
|
19
|
+
allocation: "reserved",
|
|
20
|
+
layout: e.layout
|
|
21
|
+
} : { allocation: "overlay" };
|
|
22
|
+
}
|
|
23
|
+
function i(e, t, n) {
|
|
24
|
+
if (e.feasible) return t ? o(t, n, e.bounds) : s({
|
|
25
|
+
...e,
|
|
26
|
+
cue: n,
|
|
27
|
+
position: e.destination.position
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function a(e, t) {
|
|
31
|
+
let n = t === "left" || t === "right";
|
|
32
|
+
return {
|
|
33
|
+
cue: {
|
|
34
|
+
x: e.x + (t === "right" ? e.width / 2 : 0),
|
|
35
|
+
y: e.y + (t === "bottom" ? e.height / 2 : 0),
|
|
36
|
+
width: n ? e.width / 2 : e.width,
|
|
37
|
+
height: n ? e.height : e.height / 2
|
|
38
|
+
},
|
|
39
|
+
seams: {
|
|
40
|
+
kind: "split",
|
|
41
|
+
edges: [{
|
|
42
|
+
side: {
|
|
43
|
+
left: "right",
|
|
44
|
+
right: "left",
|
|
45
|
+
top: "bottom",
|
|
46
|
+
bottom: "top"
|
|
47
|
+
}[t],
|
|
48
|
+
offset: 0,
|
|
49
|
+
fraction: .5
|
|
50
|
+
}]
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function o(e, t, n) {
|
|
55
|
+
let r = e.seams.edges[0], i = r.side === "left" || r.side === "right", { x: a, y: o } = l(e.cue, r.side, 0);
|
|
56
|
+
if (a < n.x || a >= n.x + n.width || o < n.y || o >= n.y + n.height) return;
|
|
57
|
+
let s = i ? (o - t.y) / t.height : (a - t.x) / t.width;
|
|
58
|
+
return Number.isFinite(s) ? {
|
|
59
|
+
kind: "split",
|
|
60
|
+
edges: [{
|
|
61
|
+
...r,
|
|
62
|
+
fraction: s
|
|
63
|
+
}]
|
|
64
|
+
} : void 0;
|
|
65
|
+
}
|
|
66
|
+
function s(e) {
|
|
67
|
+
let { plan: t, regions: n, sourceKey: r, position: i } = e;
|
|
68
|
+
if (t.kind === "tab" || i === "tab") return;
|
|
69
|
+
let a = r.split("."), o = Number(a.pop()), s = n.find((e) => e.key === a.join(".")), l = n.find((e) => e.key === r);
|
|
70
|
+
if (!l || s?.node.type !== "split") return;
|
|
71
|
+
let [u, f] = s.node.axis === "horizontal" ? ["left", "right"] : ["top", "bottom"], p = {
|
|
72
|
+
left: "right",
|
|
73
|
+
right: "left",
|
|
74
|
+
top: "bottom",
|
|
75
|
+
bottom: "top"
|
|
76
|
+
}[i], m = [-1, 1].flatMap((r) => {
|
|
77
|
+
let i = n.find((e) => e.key === `${s.key}.${o + r}`), a = r < 0 ? u : f;
|
|
78
|
+
if (!i || t.kind === "split" && a !== p) return [];
|
|
79
|
+
let m = d(e, a, c(l.rect, i.rect, a));
|
|
80
|
+
return m ? [m] : [];
|
|
81
|
+
});
|
|
82
|
+
return m.length ? {
|
|
83
|
+
kind: {
|
|
84
|
+
reorder: "insert",
|
|
85
|
+
insert: "insert",
|
|
86
|
+
split: "split"
|
|
87
|
+
}[t.kind],
|
|
88
|
+
edges: m
|
|
89
|
+
} : void 0;
|
|
90
|
+
}
|
|
91
|
+
function c(e, t, n) {
|
|
92
|
+
let r = {
|
|
93
|
+
left: e.x - t.x - t.width,
|
|
94
|
+
right: t.x - e.x - e.width,
|
|
95
|
+
top: e.y - t.y - t.height,
|
|
96
|
+
bottom: t.y - e.y - e.height
|
|
97
|
+
};
|
|
98
|
+
return Math.max(0, r[n]) / 2;
|
|
99
|
+
}
|
|
100
|
+
function l(e, t, n) {
|
|
101
|
+
switch (t) {
|
|
102
|
+
case "left": return {
|
|
103
|
+
x: e.x - n,
|
|
104
|
+
y: e.y + e.height / 2
|
|
105
|
+
};
|
|
106
|
+
case "right": return {
|
|
107
|
+
x: e.x + e.width + n,
|
|
108
|
+
y: e.y + e.height / 2
|
|
109
|
+
};
|
|
110
|
+
case "top": return {
|
|
111
|
+
x: e.x + e.width / 2,
|
|
112
|
+
y: e.y - n
|
|
113
|
+
};
|
|
114
|
+
case "bottom": return {
|
|
115
|
+
x: e.x + e.width / 2,
|
|
116
|
+
y: e.y + e.height + n
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function u(e, t) {
|
|
121
|
+
return t.x >= e.x && t.x < e.x + e.width && t.y >= e.y && t.y < e.y + e.height;
|
|
122
|
+
}
|
|
123
|
+
function d(e, t, n) {
|
|
124
|
+
let { cue: r, bounds: i } = e, a = l(e.sourceRect, t, n);
|
|
125
|
+
if (!u(i, a)) return;
|
|
126
|
+
let o = t === "left" || t === "right", s = o ? r.height : r.width;
|
|
127
|
+
if (s <= 0) return;
|
|
128
|
+
let c = ((o ? a.y : a.x) - (o ? r.y : r.x)) / s;
|
|
129
|
+
return c >= 0 && c <= 1 ? {
|
|
130
|
+
side: t,
|
|
131
|
+
offset: n,
|
|
132
|
+
fraction: c
|
|
133
|
+
} : void 0;
|
|
134
|
+
}
|
|
135
|
+
export { r as getOfferAllocation, n as getOfferPresentation };
|
|
136
|
+
|
|
137
|
+
//# sourceMappingURL=offers.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"offers.utils.js","names":["getOfferPresentation","recipient","input","group","panel","intent","splitIntent","cue","clipCue","offerSeams","getAffectedSplitContext","getOfferAllocation","plan","feasible","intentSeam","planSeamPreview","horizontal","position","rect","edge","vertical","seamPoint","x","bounds","y","fraction","parts","sourceKey","index","parent","regions","region","source","before","after","facing","edges","neighbor","delta","side","describeEdge","halfGap","gaps","r","offset","inside","point","extent"],"sources":["../../../../src/workspace/utils/presentation/offers.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 { clipCue } from '../interaction/drag-preview.utils.js';\nimport { getAffectedSplitContext } from '../placement/context.utils.js';\n\nimport type { WorkspacePlacedRegion } from '../geometry/allocation.utils.js';\nimport type { WorkspaceDragAllocation } from '../interaction/drag-preview.utils.js';\nimport type { WorkspaceDestination } from '../model/operations.utils.js';\nimport type { WorkspacePlacementPlan } from '../placement/planner.utils.js';\n\ntype WorkspaceSeamSide = 'left' | 'right' | 'top' | 'bottom';\n\nexport interface WorkspaceSeamPreview {\n kind: 'split' | 'insert';\n edges: { side: WorkspaceSeamSide; offset: number; fraction: number }[];\n}\n\ninterface SeamInput {\n plan: WorkspacePlacementPlan;\n regions: WorkspacePlacedRegion[];\n sourceKey: string;\n sourceRect: Rect;\n cue: Rect;\n bounds: Rect;\n position: WorkspaceDestination['position'];\n}\n\n/** Separates a group split's intended half from its constrained committed allocation. */\nexport function getOfferPresentation(input: {\n plan: WorkspacePlacementPlan;\n regions: WorkspacePlacedRegion[];\n sourceKey: string;\n sourceRect: Rect;\n cue: Rect;\n bounds: Rect;\n destination: WorkspaceDestination;\n feasible: boolean;\n split?: {\n source: string[];\n regions: WorkspacePlacedRegion[];\n groups: { panels: { id: string }[]; rect: Rect }[];\n };\n client(rect: Rect): Rect;\n}) {\n const recipient = input.split?.groups.find(group =>\n group.panels.some(panel => panel.id === input.destination.target)\n );\n const intent =\n recipient && input.destination.position !== 'tab'\n ? splitIntent(input.client(recipient.rect), input.destination.position)\n : undefined;\n const cue = clipCue(intent?.cue ?? input.cue, input.bounds);\n return {\n cue,\n seams: offerSeams(input, intent, cue),\n context:\n recipient && input.split\n ? getAffectedSplitContext({\n baseline: input.split.regions,\n achieved: input.regions,\n source: input.split.source,\n recipient: recipient.panels.map(panel => panel.id)\n })\n : input.plan.context\n };\n}\n\n/** Chooses live reservation separately from the unchanged candidate and commitment. */\nexport function getOfferAllocation(plan: WorkspacePlacementPlan, feasible: boolean): WorkspaceDragAllocation {\n return (plan.kind === 'reorder' || plan.kind === 'tab' || plan.kind === 'insert') && feasible\n ? { allocation: 'reserved', layout: plan.layout }\n : { allocation: 'overlay' };\n}\n\nfunction offerSeams(\n input: Parameters<typeof getOfferPresentation>[0],\n intent: ReturnType<typeof splitIntent> | undefined,\n cue: Rect\n): WorkspaceSeamPreview | undefined {\n if (!input.feasible) return undefined;\n if (intent) return intentSeam(intent, cue, input.bounds);\n return planSeamPreview({ ...input, cue, position: input.destination.position });\n}\n\nfunction splitIntent(rect: Rect, position: Exclude<WorkspaceDestination['position'], 'tab'>) {\n const horizontal = position === 'left' || position === 'right';\n const cue = {\n x: rect.x + (position === 'right' ? rect.width / 2 : 0),\n y: rect.y + (position === 'bottom' ? rect.height / 2 : 0),\n width: horizontal ? rect.width / 2 : rect.width,\n height: horizontal ? rect.height : rect.height / 2\n };\n const side = { left: 'right', right: 'left', top: 'bottom', bottom: 'top' } as const;\n const seams: WorkspaceSeamPreview = { kind: 'split', edges: [{ side: side[position], offset: 0, fraction: 0.5 }] };\n return { cue, seams };\n}\n\nfunction intentSeam(\n intent: { cue: Rect; seams: WorkspaceSeamPreview },\n cue: Rect,\n bounds: Rect\n): WorkspaceSeamPreview | undefined {\n const edge = intent.seams.edges[0]!;\n const vertical = edge.side === 'left' || edge.side === 'right';\n const { x, y } = seamPoint(intent.cue, edge.side, 0);\n if (x < bounds.x || x >= bounds.x + bounds.width || y < bounds.y || y >= bounds.y + bounds.height) return undefined;\n const fraction = vertical ? (y - cue.y) / cue.height : (x - cue.x) / cue.width;\n return Number.isFinite(fraction) ? { kind: 'split', edges: [{ ...edge, fraction }] } : undefined;\n}\n\n/** Describes only the actual adjoining seams of one evaluated candidate. */\nfunction planSeamPreview(input: SeamInput): WorkspaceSeamPreview | undefined {\n const { plan, regions, sourceKey, position } = input;\n if (plan.kind === 'tab' || position === 'tab') return undefined;\n const parts = sourceKey.split('.');\n const index = Number(parts.pop());\n const parent = regions.find(region => region.key === parts.join('.'));\n const source = regions.find(region => region.key === sourceKey);\n if (!source || parent?.node.type !== 'split') return undefined;\n const horizontal = parent.node.axis === 'horizontal';\n const [before, after] = horizontal ? (['left', 'right'] as const) : (['top', 'bottom'] as const);\n const facing = { left: 'right', right: 'left', top: 'bottom', bottom: 'top' }[position];\n const edges = [-1, 1].flatMap(delta => {\n const neighbor = regions.find(region => region.key === `${parent.key}.${index + delta}`);\n const side = delta < 0 ? before : after;\n if (!neighbor || (plan.kind === 'split' && side !== facing)) return [];\n const offset = halfGap(source.rect, neighbor.rect, side);\n const edge = describeEdge(input, side, offset);\n return edge ? [edge] : [];\n });\n const kind = { reorder: 'insert', insert: 'insert', split: 'split' } as const;\n return edges.length ? { kind: kind[plan.kind], edges } : undefined;\n}\n\nfunction halfGap(source: Rect, neighbor: Rect, side: WorkspaceSeamSide) {\n const gaps = {\n left: source.x - neighbor.x - neighbor.width,\n right: neighbor.x - source.x - source.width,\n top: source.y - neighbor.y - neighbor.height,\n bottom: neighbor.y - source.y - source.height\n };\n return Math.max(0, gaps[side]) / 2;\n}\n\nfunction seamPoint(r: Rect, side: WorkspaceSeamSide, offset: number) {\n switch (side) {\n case 'left':\n return { x: r.x - offset, y: r.y + r.height / 2 };\n case 'right':\n return { x: r.x + r.width + offset, y: r.y + r.height / 2 };\n case 'top':\n return { x: r.x + r.width / 2, y: r.y - offset };\n case 'bottom':\n return { x: r.x + r.width / 2, y: r.y + r.height + offset };\n }\n}\n\nfunction inside(rect: Rect, point: Point) {\n return point.x >= rect.x && point.x < rect.x + rect.width && point.y >= rect.y && point.y < rect.y + rect.height;\n}\n\nfunction describeEdge(input: SeamInput, side: WorkspaceSeamSide, offset: number) {\n const { cue, bounds } = input;\n const point = seamPoint(input.sourceRect, side, offset);\n if (!inside(bounds, point)) return undefined;\n const vertical = side === 'left' || side === 'right';\n const extent = vertical ? cue.height : cue.width;\n if (extent <= 0) return undefined;\n const fraction = ((vertical ? point.y : point.x) - (vertical ? cue.y : cue.x)) / extent;\n return fraction >= 0 && fraction <= 1 ? { side, offset, fraction } : undefined;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Rect } from '@nvidia-elements/core/internal';
|
|
2
|
+
import type { WorkspacePlacedRegion } from '../geometry/allocation.utils.js';
|
|
3
|
+
import type { WorkspaceDragPreview } from '../interaction/drag-preview.utils.js';
|
|
4
|
+
export declare function shouldEmphasizeReservedDestination(preview: WorkspaceDragPreview): boolean;
|
|
5
|
+
/** Rounds only corners shared with the visible group geometry. */
|
|
6
|
+
export declare function getRegionCornerStyle(rect: Rect, regions: WorkspacePlacedRegion[]): string;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// src/workspace/utils/presentation/preview.utils.ts
|
|
2
|
+
function e(e) {
|
|
3
|
+
return !e.blocked && "allocation" in e && e.allocation === "reserved" && (e.intent.kind === "order" || e.intent.kind === "insert" || e.phase === "detached" && e.intent.kind === "invalid" && e.cue.kind === "group");
|
|
4
|
+
}
|
|
5
|
+
function t(e, t) {
|
|
6
|
+
let n = [
|
|
7
|
+
[
|
|
8
|
+
"top-left",
|
|
9
|
+
0,
|
|
10
|
+
0
|
|
11
|
+
],
|
|
12
|
+
[
|
|
13
|
+
"top-right",
|
|
14
|
+
1,
|
|
15
|
+
0
|
|
16
|
+
],
|
|
17
|
+
[
|
|
18
|
+
"bottom-right",
|
|
19
|
+
1,
|
|
20
|
+
1
|
|
21
|
+
],
|
|
22
|
+
[
|
|
23
|
+
"bottom-left",
|
|
24
|
+
0,
|
|
25
|
+
1
|
|
26
|
+
]
|
|
27
|
+
], r = ["border-radius:var(--_workspace-border-radius)"];
|
|
28
|
+
for (let [i, a, o] of n) {
|
|
29
|
+
let n = e.x + a * e.width, s = e.y + o * e.height;
|
|
30
|
+
t.some(({ node: e, rect: t }) => e.type === "group" && Math.abs(n - t.x - a * t.width) < 1e-6 && Math.abs(s - t.y - o * t.height) < 1e-6) || r.push(`border-${i}-radius:0px`);
|
|
31
|
+
}
|
|
32
|
+
return r.join(";");
|
|
33
|
+
}
|
|
34
|
+
export { t as getRegionCornerStyle, e as shouldEmphasizeReservedDestination };
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=preview.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview.utils.js","names":["shouldEmphasizeReservedDestination","preview","getRegionCornerStyle","corners","styles","corner","right","bottom","x","rect","y","regions","group","node"],"sources":["../../../../src/workspace/utils/presentation/preview.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Rect } from '@nvidia-elements/core/internal';\n\nimport type { WorkspacePlacedRegion } from '../geometry/allocation.utils.js';\nimport type { WorkspaceDragPreview } from '../interaction/drag-preview.utils.js';\n\nexport function shouldEmphasizeReservedDestination(preview: WorkspaceDragPreview) {\n return (\n !preview.blocked &&\n 'allocation' in preview &&\n preview.allocation === 'reserved' &&\n (preview.intent.kind === 'order' ||\n preview.intent.kind === 'insert' ||\n (preview.phase === 'detached' && preview.intent.kind === 'invalid' && preview.cue.kind === 'group'))\n );\n}\n\n/** Rounds only corners shared with the visible group geometry. */\nexport function getRegionCornerStyle(rect: Rect, regions: WorkspacePlacedRegion[]): string {\n const corners = [\n ['top-left', 0, 0],\n ['top-right', 1, 0],\n ['bottom-right', 1, 1],\n ['bottom-left', 0, 1]\n ] as const;\n const styles = ['border-radius:var(--_workspace-border-radius)'];\n for (const [corner, right, bottom] of corners) {\n const x = rect.x + right * rect.width;\n const y = rect.y + bottom * rect.height;\n const rounded = regions.some(\n ({ node, rect: group }) =>\n node.type === 'group' &&\n Math.abs(x - group.x - right * group.width) < 0.000001 &&\n Math.abs(y - group.y - bottom * group.height) < 0.000001\n );\n if (!rounded) {\n styles.push(`border-${corner}-radius:0px`);\n }\n }\n return styles.join(';');\n}\n"],"mappings":";AAQA,SAAgBA,EAAmC,GAA+B;CAChF,OACE,CAACC,EAAQ,WACT,gBAAgBA,KAChBA,EAAQ,eAAe,eACtBA,EAAQ,OAAO,SAAS,WACvBA,EAAQ,OAAO,SAAS,YACvBA,EAAQ,UAAU,cAAcA,EAAQ,OAAO,SAAS,aAAaA,EAAQ,IAAI,SAAS;AAEjG;AAGA,SAAgBC,EAAqB,GAAY,GAA0C;CACzF,IAAMC,IAAU;EACd;GAAC;GAAY;GAAG;EAAC;EACjB;GAAC;GAAa;GAAG;EAAC;EAClB;GAAC;GAAgB;GAAG;EAAC;EACrB;GAAC;GAAe;GAAG;EAAC;CACtB,GACMC,IAAS,CAAC,+CAA+C;CAC/D,KAAK,IAAM,CAACC,GAAQC,GAAOC,MAAWJ,GAAS;EAC7C,IAAMK,IAAIC,EAAK,IAAIH,IAAQG,EAAK,OAC1BC,IAAID,EAAK,IAAIF,IAASE,EAAK;EAOjC,AANgBE,EAAQ,MACrB,EAAE,SAAM,MAAMC,QACbC,EAAK,SAAS,WACd,KAAK,IAAIL,IAAII,EAAM,IAAIN,IAAQM,EAAM,KAAK,IAAI,QAC9C,KAAK,IAAIF,IAAIE,EAAM,IAAIL,IAASK,EAAM,MAAM,IAAI,IAE/C,KACHR,EAAO,KAAK,UAAUC,EAAO,YAAY;CAE7C;CACA,OAAOD,EAAO,KAAK,GAAG;AACxB"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { LitElement, type PropertyValues } from 'lit';
|
|
2
|
+
import { DragHandle } from '@nvidia-elements/core/drag-handle';
|
|
3
|
+
import { Ghost } from '@nvidia-elements/core/ghost';
|
|
4
|
+
import { Icon } from '@nvidia-elements/core/icon';
|
|
5
|
+
import { IconButton } from '@nvidia-elements/core/icon-button';
|
|
6
|
+
import { ResizeHandle } from '@nvidia-elements/core/resize-handle';
|
|
7
|
+
import { Tabs, TabsItem, TabsItemGroup } from '@nvidia-elements/core/tabs';
|
|
8
|
+
import type { WorkspaceCommandContext } from './utils/interaction/command.utils.js';
|
|
9
|
+
import type { WorkspaceAnimationOptions } from './workspace.types.js';
|
|
10
|
+
/**
|
|
11
|
+
* @element nve-workspace
|
|
12
|
+
* @description A workspace provides a malleable arrangement of application panels in a restorable layout.
|
|
13
|
+
* @documentation https://nvidia.github.io/elements/docs/elements/workspace/
|
|
14
|
+
* @since 0.0.0
|
|
15
|
+
* @stable false
|
|
16
|
+
* @entrypoint \@nvidia-elements/core/workspace
|
|
17
|
+
* @command --enter-fullscreen - Present the invoking panel's group in native fullscreen.
|
|
18
|
+
* @command --exit-fullscreen - Exit native fullscreen.
|
|
19
|
+
* @command --toggle-fullscreen - Toggle native fullscreen for the invoking panel's group.
|
|
20
|
+
* @command --open - Open and activate the targeted supplied panel. Repeated activation is silent.
|
|
21
|
+
* @command --close - Close the targeted panel when its workspace is closable.
|
|
22
|
+
* @command --select - Activate an open supplied panel without reopening a closed panel.
|
|
23
|
+
* @command --place - Apply the invoker's typed placement request when rearrangeable; membership changes also require groupable.
|
|
24
|
+
* @slot - Workspace panels with durable IDs and application dropdown groups.
|
|
25
|
+
* @event change - Announces a committed arrangement value after interaction, commands, or reconciliation of newly supplied panels. Read value on the workspace.
|
|
26
|
+
* @event commandavailabilitychange - Command availability may have changed; query relevant commands again.
|
|
27
|
+
* @cssprop --gap - Space between groups as one nonnegative CSS length.
|
|
28
|
+
* @cssprop --border-radius - Corner radius of contained groups.
|
|
29
|
+
* @cssprop --tab-min-width - Smallest tab width before scrolling.
|
|
30
|
+
* @cssprop --tab-border - Border between tabs, after the drag handle, and before group controls without an authored suffix.
|
|
31
|
+
* @cssprop --header-control-size - Size of built-in header buttons and the base drag handle width.
|
|
32
|
+
* @cssprop --header-control-inset - Horizontal spacing around fullscreen and the drag handle.
|
|
33
|
+
* @cssprop --close-button-inset - Space after each panel close control.
|
|
34
|
+
* @cssprop --animation-duration - Duration of coordinated layout and placement transitions.
|
|
35
|
+
* @cssprop --animation-easing - Easing of coordinated layout and placement transitions.
|
|
36
|
+
* @cssprop --gutter-background - Idle separator fill.
|
|
37
|
+
* @cssprop --gutter-hover-background - Separator fill on hover.
|
|
38
|
+
* @csspart tabs - Tab strips.
|
|
39
|
+
* @csspart tabs-item - Panel selection controls.
|
|
40
|
+
* @csspart tab - Alias for panel selection controls.
|
|
41
|
+
* @csspart tabs-item-group - Tab and accessory layouts.
|
|
42
|
+
* @csspart icon-button - Built-in header icon controls.
|
|
43
|
+
* @csspart fullscreen-button - Group fullscreen control.
|
|
44
|
+
* @csspart close-button - Panel closing controls.
|
|
45
|
+
* @csspart resize-handle - Separator control.
|
|
46
|
+
* @csspart ghost - Destination and carried previews.
|
|
47
|
+
* @csspart destination-ghost - Animated insertion cue.
|
|
48
|
+
* @csspart carried-ghost - Pointer-following carried panel previews.
|
|
49
|
+
* @csspart icon - Placement status icons.
|
|
50
|
+
* @csspart blocked-icon - Unavailable placement indicator.
|
|
51
|
+
* @csspart drag-handle - Group movement control.
|
|
52
|
+
*/
|
|
53
|
+
export declare class Workspace extends LitElement {
|
|
54
|
+
#private;
|
|
55
|
+
static styles: import("lit").CSSResult[];
|
|
56
|
+
static readonly metadata: {
|
|
57
|
+
tag: string;
|
|
58
|
+
version: string;
|
|
59
|
+
children: string[];
|
|
60
|
+
};
|
|
61
|
+
static elementDefinitions: {
|
|
62
|
+
[DragHandle.metadata.tag]: typeof DragHandle;
|
|
63
|
+
[Ghost.metadata.tag]: typeof Ghost;
|
|
64
|
+
[Icon.metadata.tag]: typeof Icon;
|
|
65
|
+
[IconButton.metadata.tag]: typeof IconButton;
|
|
66
|
+
[ResizeHandle.metadata.tag]: typeof ResizeHandle;
|
|
67
|
+
[Tabs.metadata.tag]: typeof Tabs;
|
|
68
|
+
[TabsItem.metadata.tag]: typeof TabsItem;
|
|
69
|
+
[TabsItemGroup.metadata.tag]: typeof TabsItemGroup;
|
|
70
|
+
};
|
|
71
|
+
/** Overrides localized workspace controls. */
|
|
72
|
+
i18n: Partial<import("@nvidia-elements/core/internal").I18nStrings & {
|
|
73
|
+
__set: boolean;
|
|
74
|
+
}>;
|
|
75
|
+
/** Enables separator resizing. */
|
|
76
|
+
resizable: boolean;
|
|
77
|
+
/** Enables moving groups and placement commands. Dragging individual tabs also requires groupable. */
|
|
78
|
+
rearrangeable: boolean;
|
|
79
|
+
/** Enables dragging individual tabs, joining panels, and extracting panels when rearrangeable. */
|
|
80
|
+
groupable: boolean;
|
|
81
|
+
/** Enables native fullscreen commands and one persistent control per group. Turning this off preserves an accepted session and its exit control. Fullscreen does not change the saved arrangement. */
|
|
82
|
+
fullscreenable: boolean;
|
|
83
|
+
/** Radial pointer distance in CSS pixels before a carried source detaches. Captured at gesture press. */
|
|
84
|
+
detachThreshold: number;
|
|
85
|
+
/** Enables closing supplied panels. */
|
|
86
|
+
closable: boolean;
|
|
87
|
+
/** Selects separator constraint behavior. */
|
|
88
|
+
resizePolicy: 'stop' | 'propagate';
|
|
89
|
+
/** Selects panel content framing. */
|
|
90
|
+
container?: 'inset' | 'flat' | 'full';
|
|
91
|
+
/** Versioned JSON arrangement. Assignment restores without emitting change. */
|
|
92
|
+
get value(): string;
|
|
93
|
+
set value(value: string);
|
|
94
|
+
connectedCallback(): void;
|
|
95
|
+
disconnectedCallback(): void;
|
|
96
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
97
|
+
protected updated(): void;
|
|
98
|
+
/** Restores an arrangement with animated geometry while retaining application content. */
|
|
99
|
+
animateTo(value: string, options?: WorkspaceAnimationOptions): void;
|
|
100
|
+
/** Reports whether a command can change the panel identified by `context.value` in the current arrangement. Native fullscreen admission remains subject to browser permission. */
|
|
101
|
+
isCommandAvailable(command: string, context?: WorkspaceCommandContext): boolean;
|
|
102
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
103
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.examples.js","names":["workspace_examples_default"],"sources":["../../src/workspace/workspace.examples.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { html } from 'lit';\n\nimport '@nvidia-elements/core/button/define.js';\nimport '@nvidia-elements/core/dropdown/define.js';\nimport '@nvidia-elements/core/dropdown-group/define.js';\nimport '@nvidia-elements/core/icon/define.js';\nimport '@nvidia-elements/core/icon-button/define.js';\nimport '@nvidia-elements/core/menu/define.js';\nimport '@nvidia-elements/core/range/define.js';\nimport '@nvidia-elements/core/textarea/define.js';\nimport '@nvidia-elements/core/workspace/define.js';\n\nexport default { title: 'Elements/Workspace', component: 'nve-workspace' };\n\n/**\n * @summary Arrange panels in nested groups while retaining application content. Drag panel headers or tabs to move panels, group handles to move tabs together, and separators to resize.\n */\nexport const Default = {\n render: () => html`\n <nve-workspace\n groupable\n rearrangeable\n resizable\n style=\"height:600px\"\n value='{\"version\":1,\"closed\":[],\"root\":{\"type\":\"split\",\"axis\":\"horizontal\",\"weights\":[1,4],\"children\":[{\"type\":\"group\",\"panels\":[\"workspace-outline\"],\"active\":\"workspace-outline\"},{\"type\":\"split\",\"axis\":\"vertical\",\"weights\":[3,2],\"children\":[{\"type\":\"split\",\"axis\":\"horizontal\",\"weights\":[3,2],\"children\":[{\"type\":\"group\",\"panels\":[\"workspace-editor\"],\"active\":\"workspace-editor\"},{\"type\":\"group\",\"panels\":[\"workspace-preview\"],\"active\":\"workspace-preview\"}]},{\"type\":\"group\",\"panels\":[\"workspace-notes\",\"workspace-activity\",\"workspace-tasks\"],\"active\":\"workspace-notes\"}]}]}}'>\n <nve-workspace-panel id=\"workspace-outline\">\n <nve-workspace-panel-header>Outline</nve-workspace-panel-header>\n <nve-workspace-panel-content>Outline content</nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"workspace-editor\">\n <nve-workspace-panel-header>Editor</nve-workspace-panel-header>\n <nve-workspace-panel-content>\n <nve-textarea><textarea aria-label=\"Editor\">Editor content</textarea></nve-textarea>\n </nve-workspace-panel-content>\n <nve-workspace-panel-footer>Ready</nve-workspace-panel-footer>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"workspace-preview\">\n <nve-workspace-panel-header>Preview</nve-workspace-panel-header>\n <nve-workspace-panel-content>Preview content</nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"workspace-notes\">\n <nve-workspace-panel-header>Notes</nve-workspace-panel-header>\n <nve-workspace-panel-content>Notes content</nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"workspace-activity\">\n <nve-workspace-panel-header>Activity</nve-workspace-panel-header>\n <nve-workspace-panel-content>Activity content</nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"workspace-tasks\">\n <nve-workspace-panel-header>Tasks</nve-workspace-panel-header>\n <nve-workspace-panel-content>Tasks content</nve-workspace-panel-content>\n </nve-workspace-panel>\n </nve-workspace>\n `\n};\n\n/**\n * @summary Resize groups within a fixed arrangement and switch tabs while retaining application content.\n */\nexport const Resizable = {\n render: () => html`\n <nve-workspace\n resizable\n value='{\"version\":1,\"root\":{\"type\":\"split\",\"axis\":\"horizontal\",\"weights\":[2,1],\"children\":[{\"type\":\"group\",\"panels\":[\"editor\",\"notes\"],\"active\":\"editor\"},{\"type\":\"group\",\"panels\":[\"preview\"],\"active\":\"preview\"}]},\"closed\":[]}'\n style=\"height:420px\">\n <nve-workspace-panel id=\"editor\">\n <nve-workspace-panel-header>Editor</nve-workspace-panel-header>\n <nve-workspace-panel-content>\n <nve-textarea><textarea aria-label=\"Editor\">Editor content</textarea></nve-textarea>\n </nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"preview\">\n <nve-workspace-panel-header>Preview</nve-workspace-panel-header>\n <nve-workspace-panel-content>Preview content</nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"notes\">\n <nve-workspace-panel-header>Notes</nve-workspace-panel-header>\n <nve-workspace-panel-content>Notes content</nve-workspace-panel-content>\n </nve-workspace-panel>\n </nve-workspace>\n `\n};\n\n/**\n * @summary Rearrange panels while keeping tabbed panels together.\n */\nexport const Rearrangeable = {\n render: () => html`\n <nve-workspace\n rearrangeable\n resizable\n style=\"height:420px\"\n value='{\"version\":1,\"closed\":[],\"root\":{\"type\":\"split\",\"axis\":\"horizontal\",\"weights\":[2,1],\"children\":[{\"type\":\"group\",\"panels\":[\"editor\",\"notes\"],\"active\":\"editor\"},{\"type\":\"group\",\"panels\":[\"preview\"],\"active\":\"preview\"}]}}'>\n <nve-workspace-panel id=\"editor\">\n <nve-workspace-panel-header>Editor</nve-workspace-panel-header>\n <nve-workspace-panel-content>\n <nve-textarea><textarea aria-label=\"Editor\">Editor content</textarea></nve-textarea>\n </nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"preview\">\n <nve-workspace-panel-header>Preview</nve-workspace-panel-header>\n <nve-workspace-panel-content>Preview content</nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"notes\">\n <nve-workspace-panel-header>Notes</nve-workspace-panel-header>\n <nve-workspace-panel-content>Notes content</nve-workspace-panel-content>\n </nve-workspace-panel>\n </nve-workspace>\n `\n};\n\n/**\n * @summary Join panels into tabbed groups or move individual tabs out.\n */\nexport const Groupable = {\n render: () => html`\n <div id=\"regroup-example\" nve-layout=\"column gap:md\">\n <nve-button>Reset layout</nve-button>\n <nve-workspace\n rearrangeable\n groupable\n resizable\n style=\"height:420px\"\n value='{\"version\":1,\"closed\":[],\"root\":{\"type\":\"split\",\"axis\":\"horizontal\",\"weights\":[2,1],\"children\":[{\"type\":\"group\",\"panels\":[\"group-editor\",\"group-notes\"],\"active\":\"group-editor\"},{\"type\":\"group\",\"panels\":[\"group-preview\"],\"active\":\"group-preview\"}]}}'>\n <nve-workspace-panel id=\"group-editor\">\n <nve-workspace-panel-header>Editor</nve-workspace-panel-header>\n <nve-workspace-panel-content>\n <nve-textarea><textarea aria-label=\"Editor\">Editor content</textarea></nve-textarea>\n </nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"group-notes\">\n <nve-workspace-panel-header>Notes</nve-workspace-panel-header>\n <nve-workspace-panel-content>Notes content</nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"group-preview\">\n <nve-workspace-panel-header>Preview</nve-workspace-panel-header>\n <nve-workspace-panel-content>Preview content</nve-workspace-panel-content>\n </nve-workspace-panel>\n </nve-workspace>\n <script type=\"module\">\n const example = document.querySelector('#regroup-example');\n const workspace = example.querySelector('nve-workspace');\n const initialValue = workspace.getAttribute('value');\n example.querySelector('nve-button').addEventListener('click', () => {\n workspace.value = initialValue;\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Close and reopen panels while retaining their positions and application content.\n */\nexport const Closable = {\n render: () => html`\n <div id=\"open-close-example\" nve-layout=\"column gap:md\">\n <div nve-layout=\"row gap:md align:space-between align:wrap\">\n <nve-button id=\"reset-open-close\">Reset layout</nve-button>\n <div nve-layout=\"row gap:sm\">\n <nve-button command=\"--open\" commandfor=\"retained-editor\">Open editor</nve-button>\n <nve-button command=\"--close\" commandfor=\"retained-editor\">Close editor</nve-button>\n </div>\n </div>\n <nve-workspace\n closable\n groupable\n rearrangeable\n resizable\n style=\"height:420px\"\n value='{\"version\":1,\"root\":{\"type\":\"split\",\"axis\":\"horizontal\",\"weights\":[2,1],\"children\":[{\"type\":\"group\",\"panels\":[\"retained-editor\",\"retained-notes\"],\"active\":\"retained-editor\"},{\"type\":\"group\",\"panels\":[\"restorable-preview\"],\"active\":\"restorable-preview\"}]},\"closed\":[]}'>\n <nve-workspace-panel id=\"retained-editor\">\n <nve-workspace-panel-header>Editor</nve-workspace-panel-header>\n <nve-workspace-panel-content>\n <nve-textarea><textarea aria-label=\"Editor\">Editor content</textarea></nve-textarea>\n </nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"restorable-preview\">\n <nve-workspace-panel-header>Preview</nve-workspace-panel-header>\n <nve-workspace-panel-content>Preview content</nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"retained-notes\">\n <nve-workspace-panel-header>Notes</nve-workspace-panel-header>\n <nve-workspace-panel-content>Notes content</nve-workspace-panel-content>\n </nve-workspace-panel>\n </nve-workspace>\n <script type=\"module\">\n const example = document.querySelector('#open-close-example');\n const workspace = example.querySelector('nve-workspace');\n const initialValue = workspace.getAttribute('value');\n example.querySelector('#reset-open-close').addEventListener('click', () => {\n workspace.value = initialValue;\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Expand a group and its tabs to full screen.\n */\nexport const Fullscreenable = {\n render: () => html`\n <div id=\"fullscreen-example\" nve-layout=\"column gap:md\">\n <nve-button>Reset layout</nve-button>\n <nve-workspace\n fullscreenable\n closable\n rearrangeable\n groupable\n resizable\n style=\"height:420px\"\n value='{\"version\":1,\"closed\":[],\"root\":{\"type\":\"split\",\"axis\":\"horizontal\",\"weights\":[2,1],\"children\":[{\"type\":\"group\",\"panels\":[\"fullscreen-editor\",\"fullscreen-notes\"],\"active\":\"fullscreen-editor\"},{\"type\":\"group\",\"panels\":[\"fullscreen-preview\"],\"active\":\"fullscreen-preview\"}]}}'>\n <nve-workspace-panel id=\"fullscreen-editor\">\n <nve-workspace-panel-header>Editor</nve-workspace-panel-header>\n <nve-workspace-panel-content>\n <nve-textarea><textarea aria-label=\"Editor\">Editor content</textarea></nve-textarea>\n </nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"fullscreen-notes\">\n <nve-workspace-panel-header>Notes</nve-workspace-panel-header>\n <nve-workspace-panel-content>Notes content</nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"fullscreen-preview\">\n <nve-workspace-panel-header>Preview</nve-workspace-panel-header>\n <nve-workspace-panel-content>Preview content</nve-workspace-panel-content>\n </nve-workspace-panel>\n </nve-workspace>\n <script type=\"module\">\n const example = document.querySelector('#fullscreen-example');\n const workspace = example.querySelector('nve-workspace');\n const initialValue = workspace.getAttribute('value');\n example.querySelector('nve-button').addEventListener('click', () => {\n workspace.value = initialValue;\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Add custom menus that use invoker commands to move, split, or close panels and toggle group fullscreen alongside application actions.\n */\n// eslint-disable-next-line local-typescript/example-template-size -- Keep the complete menu composition readable without compressing its markup.\nexport const CustomPanelActions = {\n render: () => html`\n <div nve-layout=\"column gap:md\">\n <nve-button id=\"a-reopen\" popovertarget=\"a-open\" disabled>Reopen</nve-button>\n <nve-workspace\n id=\"a-demo\"\n fullscreenable\n groupable\n rearrangeable\n closable\n resizable\n style=\"height:420px\"\n value='{\"version\":1,\"closed\":[],\"root\":{\"type\":\"split\",\"axis\":\"horizontal\",\"weights\":[2,1],\"children\":[{\"type\":\"group\",\"panels\":[\"a-editor\",\"a-notes\"],\"active\":\"a-editor\"},{\"type\":\"group\",\"panels\":[\"a-preview\"],\"active\":\"a-preview\"}]}}'>\n <nve-workspace-panel id=\"a-editor\">\n <nve-workspace-panel-header>\n Editor\n <nve-icon-button slot=\"suffix\" icon-name=\"more-actions\" container=\"flat\" size=\"sm\"\n aria-label=\"Editor actions\" value=\"a-editor\" popovertarget=\"a-menu\"></nve-icon-button>\n </nve-workspace-panel-header>\n <nve-workspace-panel-content>\n <nve-textarea><textarea aria-label=\"Editor\">Editor content</textarea></nve-textarea>\n </nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"a-notes\">\n <nve-workspace-panel-header>\n Notes\n <nve-icon-button slot=\"suffix\" icon-name=\"more-actions\" container=\"flat\" size=\"sm\"\n aria-label=\"Notes actions\" value=\"a-notes\" popovertarget=\"a-menu\"></nve-icon-button>\n </nve-workspace-panel-header>\n <nve-workspace-panel-content>Notes content</nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"a-preview\">\n <nve-workspace-panel-header>\n Preview\n <nve-icon-button slot=\"suffix\" icon-name=\"more-actions\" container=\"flat\" size=\"sm\"\n aria-label=\"Preview actions\" value=\"a-preview\" popovertarget=\"a-menu\"></nve-icon-button>\n </nve-workspace-panel-header>\n <nve-workspace-panel-content>Preview content</nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-dropdown-group>\n <nve-dropdown id=\"a-menu\">\n <nve-menu>\n <nve-menu-item command=\"--toggle-fullscreen\">Fullscreen</nve-menu-item>\n <nve-menu-item popovertarget=\"a-move\">\n Move to\n <nve-icon name=\"caret\" direction=\"right\" size=\"sm\" slot=\"suffix\"></nve-icon>\n </nve-menu-item>\n <nve-menu-item popovertarget=\"a-split\">\n Split\n <nve-icon name=\"caret\" direction=\"right\" size=\"sm\" slot=\"suffix\"></nve-icon>\n </nve-menu-item>\n <nve-menu-item command=\"--close\">Close</nve-menu-item>\n </nve-menu>\n </nve-dropdown>\n <nve-dropdown id=\"a-move\" position=\"right\">\n <nve-menu>\n <nve-menu-item command=\"--place\" data-target=\"a-editor\">Editor</nve-menu-item>\n <nve-menu-item command=\"--place\" data-target=\"a-notes\">Notes</nve-menu-item>\n <nve-menu-item command=\"--place\" data-target=\"a-preview\">Preview</nve-menu-item>\n </nve-menu>\n </nve-dropdown>\n <nve-dropdown id=\"a-open\" position=\"bottom\">\n <nve-menu>\n <nve-menu-item command=\"--open\" data-target=\"a-editor\">Editor</nve-menu-item>\n <nve-menu-item command=\"--open\" data-target=\"a-notes\">Notes</nve-menu-item>\n <nve-menu-item command=\"--open\" data-target=\"a-preview\">Preview</nve-menu-item>\n </nve-menu>\n </nve-dropdown>\n <nve-dropdown id=\"a-split\" position=\"right\">\n <nve-menu>\n <nve-menu-item command=\"--place\" data-side=\"left\">Left</nve-menu-item>\n <nve-menu-item command=\"--place\" data-side=\"right\">Right</nve-menu-item>\n <nve-menu-item command=\"--place\" data-side=\"top\">Above</nve-menu-item>\n <nve-menu-item command=\"--place\" data-side=\"bottom\">Below</nve-menu-item>\n </nve-menu>\n </nve-dropdown>\n </nve-dropdown-group>\n </nve-workspace>\n <script type=\"module\">\n const workspace = document.querySelector('#a-demo');\n const dropdownGroup = workspace.querySelector('nve-dropdown-group');\n const reopen = document.querySelector('#a-reopen');\n let panelId;\n\n function refresh() {\n const { root, closed } = JSON.parse(workspace.value);\n const labels = new Map(\n [...workspace.querySelectorAll(':scope > nve-workspace-panel')].map(panel => [\n panel.id,\n panel.querySelector('nve-workspace-panel-header').textContent.trim()\n ])\n );\n const groups = getOpenPanelGroups(root, labels, closed);\n const currentGroup = groups.find(ids => ids.includes(panelId));\n const splitTarget = currentGroup?.find(id => id !== panelId);\n\n updateMoveMenu(groups, currentGroup, labels);\n updateReopenMenu(closed, labels);\n\n for (const item of dropdownGroup.querySelectorAll('[command]')) {\n item.commandForElement = workspace;\n item.value = item.command === '--open' ? item.dataset.target : panelId;\n if (item.dataset.side) {\n item.placement = { operation: 'split', target: splitTarget, position: item.dataset.side };\n }\n item.disabled = item.style.display === 'none' || !workspace.isCommandAvailable(item.command, item);\n }\n\n for (const trigger of dropdownGroup.querySelectorAll('[popovertarget]')) {\n const items = trigger.popoverTargetElement.querySelectorAll('[command]');\n trigger.disabled = [...items].every(item => item.disabled);\n }\n reopen.disabled = !closed.some(id => labels.has(id));\n }\n\n function getOpenPanelGroups(node, labels, closed) {\n if (!node) return [];\n if (node.type === 'group') {\n return [node.panels.filter(id => labels.has(id) && !closed.includes(id))];\n }\n return node.children.flatMap(child => getOpenPanelGroups(child, labels, closed));\n }\n\n function updateMoveMenu(groups, currentGroup, labels) {\n for (const item of dropdownGroup.querySelectorAll('#a-move [data-target]')) {\n const target = item.dataset.target;\n const members = groups.find(ids => ids[0] === target && ids !== currentGroup);\n item.style.display = members ? '' : 'none';\n item.placement = { operation: 'join', target };\n if (members) {\n item.textContent = members.map(id => labels.get(id)).join(', ');\n }\n }\n }\n\n function updateReopenMenu(closed, labels) {\n for (const item of dropdownGroup.querySelectorAll('#a-open [data-target]')) {\n const target = item.dataset.target;\n item.style.display = labels.has(target) && closed.includes(target) ? '' : 'none';\n }\n }\n\n dropdownGroup.addEventListener('beforetoggle', event => {\n if (event.newState !== 'open') return;\n if (event.target.id === 'a-menu') panelId = event.source?.value;\n refresh();\n }, true);\n workspace.addEventListener('commandavailabilitychange', refresh);\n workspace.addEventListener('command', () => dropdownGroup.close());\n </script>\n </div>\n `\n};\n\n/**\n * @summary Match the surrounding layout with inset, flat, or full container framing.\n * @tags test-case\n */\nexport const Container = {\n render: () => html`\n <div nve-layout=\"column gap:md\">\n <nve-workspace\n container=\"inset\"\n resizable\n style=\"height:220px\"\n value='{\"version\":1,\"closed\":[],\"root\":{\"type\":\"split\",\"axis\":\"horizontal\",\"weights\":[1,1],\"children\":[{\"type\":\"group\",\"panels\":[\"container-inset\"],\"active\":\"container-inset\"},{\"type\":\"group\",\"panels\":[\"container-inset-preview\"],\"active\":\"container-inset-preview\"}]}}'>\n <nve-workspace-panel id=\"container-inset\">\n <nve-workspace-panel-header>Editor (inset)</nve-workspace-panel-header>\n <nve-workspace-panel-content>\n <nve-textarea><textarea aria-label=\"Editor\">Editor content</textarea></nve-textarea>\n </nve-workspace-panel-content>\n <nve-workspace-panel-footer>Ready</nve-workspace-panel-footer>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"container-inset-preview\">\n <nve-workspace-panel-header>Preview</nve-workspace-panel-header>\n <nve-workspace-panel-content>Preview content</nve-workspace-panel-content>\n </nve-workspace-panel>\n </nve-workspace>\n <nve-workspace\n container=\"flat\"\n resizable\n style=\"height:220px\"\n value='{\"version\":1,\"closed\":[],\"root\":{\"type\":\"split\",\"axis\":\"horizontal\",\"weights\":[1,1],\"children\":[{\"type\":\"group\",\"panels\":[\"container-flat\"],\"active\":\"container-flat\"},{\"type\":\"group\",\"panels\":[\"container-flat-preview\"],\"active\":\"container-flat-preview\"}]}}'>\n <nve-workspace-panel id=\"container-flat\">\n <nve-workspace-panel-header>Editor (flat)</nve-workspace-panel-header>\n <nve-workspace-panel-content>\n <nve-textarea><textarea aria-label=\"Editor\">Editor content</textarea></nve-textarea>\n </nve-workspace-panel-content>\n <nve-workspace-panel-footer>Ready</nve-workspace-panel-footer>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"container-flat-preview\">\n <nve-workspace-panel-header>Preview</nve-workspace-panel-header>\n <nve-workspace-panel-content>Preview content</nve-workspace-panel-content>\n </nve-workspace-panel>\n </nve-workspace>\n <nve-workspace\n container=\"full\"\n resizable\n style=\"height:220px\"\n value='{\"version\":1,\"closed\":[],\"root\":{\"type\":\"split\",\"axis\":\"horizontal\",\"weights\":[1,1],\"children\":[{\"type\":\"group\",\"panels\":[\"container-full\"],\"active\":\"container-full\"},{\"type\":\"group\",\"panels\":[\"container-full-preview\"],\"active\":\"container-full-preview\"}]}}'>\n <nve-workspace-panel id=\"container-full\">\n <nve-workspace-panel-header>Editor (full)</nve-workspace-panel-header>\n <nve-workspace-panel-content>\n <nve-textarea><textarea aria-label=\"Editor\">Editor content</textarea></nve-textarea>\n </nve-workspace-panel-content>\n <nve-workspace-panel-footer>Ready</nve-workspace-panel-footer>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"container-full-preview\">\n <nve-workspace-panel-header>Preview</nve-workspace-panel-header>\n <nve-workspace-panel-content>Preview content</nve-workspace-panel-content>\n </nve-workspace-panel>\n </nve-workspace>\n </div>\n `\n};\n\n/**\n * @summary Customize header spacing, control sizes, and panel corners for a compact workspace.\n * @tags theme\n */\nexport const CustomHeaders = {\n render: () => html`\n <div id=\"compact-example\" nve-layout=\"column gap:md\">\n <nve-button>Reset layout</nve-button>\n <style>\n #condensed-workspace > nve-workspace-panel {\n --box-shadow: none;\n }\n #condensed-workspace nve-workspace-panel-header {\n --min-height: var(--nve-ref-size-800);\n --padding: var(--nve-ref-size-100) var(--nve-ref-size-100) var(--nve-ref-size-100) var(--nve-ref-size-250);\n }\n </style>\n <nve-workspace\n id=\"condensed-workspace\"\n rearrangeable\n groupable\n closable\n resizable\n fullscreenable\n style=\"--gap:0;--border-radius:0;--header-control-size:var(--nve-ref-size-600);--close-button-inset:var(--nve-ref-size-100);height:300px\"\n value='{\"version\":1,\"closed\":[],\"root\":{\"type\":\"split\",\"axis\":\"horizontal\",\"weights\":[2,1],\"children\":[{\"type\":\"group\",\"panels\":[\"condensed-editor\",\"condensed-notes\"],\"active\":\"condensed-editor\"},{\"type\":\"group\",\"panels\":[\"condensed-preview\"],\"active\":\"condensed-preview\"}]}}'>\n <nve-workspace-panel id=\"condensed-editor\">\n <nve-workspace-panel-header>Editor</nve-workspace-panel-header>\n <nve-workspace-panel-content>\n <nve-textarea><textarea aria-label=\"Editor\">Editor content</textarea></nve-textarea>\n </nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"condensed-notes\">\n <nve-workspace-panel-header>Notes</nve-workspace-panel-header>\n <nve-workspace-panel-content>Notes content</nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"condensed-preview\">\n <nve-workspace-panel-header>Preview</nve-workspace-panel-header>\n <nve-workspace-panel-content>Preview content</nve-workspace-panel-content>\n </nve-workspace-panel>\n </nve-workspace>\n <script type=\"module\">\n const example = document.querySelector('#compact-example');\n const workspace = example.querySelector('nve-workspace');\n const initialValue = workspace.getAttribute('value');\n example.querySelector('nve-button').addEventListener('click', () => {\n workspace.value = initialValue;\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Save and restore groups, split proportions, and closed panels without recreating application content.\n */\nexport const SaveRestore = {\n render: () => html`\n <div nve-layout=\"column gap:md\">\n <div nve-layout=\"row gap:md align:space-between align:wrap\">\n <nve-button id=\"reset-arrangement\">Reset layout</nve-button>\n <div nve-layout=\"row gap:sm\">\n <nve-button id=\"save-arrangement\">Save layout</nve-button>\n <nve-button id=\"restore-arrangement\">Restore layout</nve-button>\n </div>\n </div>\n <nve-workspace\n id=\"saved-arrangement\"\n groupable\n rearrangeable\n closable\n resizable\n style=\"height:420px\"\n value='{\"version\":1,\"root\":{\"type\":\"split\",\"axis\":\"horizontal\",\"weights\":[2,1],\"children\":[{\"type\":\"group\",\"panels\":[\"saved-editor\",\"saved-notes\"],\"active\":\"saved-editor\"},{\"type\":\"group\",\"panels\":[\"saved-preview\"],\"active\":\"saved-preview\"}]},\"closed\":[]}'>\n <nve-workspace-panel id=\"saved-editor\">\n <nve-workspace-panel-header>Editor</nve-workspace-panel-header>\n <nve-workspace-panel-content>\n <nve-textarea><textarea aria-label=\"Editor\">Editor content</textarea></nve-textarea>\n </nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"saved-notes\">\n <nve-workspace-panel-header>Notes</nve-workspace-panel-header>\n <nve-workspace-panel-content>Notes content</nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"saved-preview\">\n <nve-workspace-panel-header>Preview</nve-workspace-panel-header>\n <nve-workspace-panel-content>Preview content</nve-workspace-panel-content>\n </nve-workspace-panel>\n </nve-workspace>\n <script type=\"module\">\n const workspace = document.querySelector('#saved-arrangement');\n const save = document.querySelector('#save-arrangement');\n const restore = document.querySelector('#restore-arrangement');\n const reset = document.querySelector('#reset-arrangement');\n const initialValue = workspace.getAttribute('value');\n let savedValue = initialValue;\n save.addEventListener('click', () => {\n savedValue = workspace.value;\n });\n restore.addEventListener('click', () => {\n workspace.animateTo(savedValue);\n });\n reset.addEventListener('click', () => {\n workspace.animateTo(initialValue);\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary The workspace scrolls when panel minimum heights exceed the available space. Increasing its height restores resizing.\n * @tags test-case\n */\nexport const ConstrainedSpace = {\n render: () => html`\n <div id=\"constrained-example\" nve-layout=\"column gap:md\">\n <nve-range>\n <label>\n Workspace height:\n <output for=\"workspace-height\">180</output>\n px\n </label>\n <input id=\"workspace-height\" type=\"range\" min=\"180\" max=\"420\" value=\"180\" />\n </nve-range>\n <nve-button>Reset layout</nve-button>\n <nve-workspace\n groupable\n rearrangeable\n resizable\n style=\"height:180px\"\n value='{\"version\":1,\"root\":{\"type\":\"split\",\"axis\":\"vertical\",\"weights\":[1,1],\"children\":[{\"type\":\"group\",\"panels\":[\"top\"],\"active\":\"top\"},{\"type\":\"group\",\"panels\":[\"bottom\"],\"active\":\"bottom\"}]},\"closed\":[]}'>\n <nve-workspace-panel id=\"top\" min-height=\"110\">\n <nve-workspace-panel-header>Top</nve-workspace-panel-header>\n <nve-workspace-panel-content>Top content</nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"bottom\" min-height=\"110\">\n <nve-workspace-panel-header>Bottom</nve-workspace-panel-header>\n <nve-workspace-panel-content>Bottom content</nve-workspace-panel-content>\n </nve-workspace-panel>\n </nve-workspace>\n <script type=\"module\">\n const example = document.querySelector('#constrained-example');\n const workspace = example.querySelector('nve-workspace');\n const range = example.querySelector('input');\n const output = example.querySelector('output');\n const initialValue = workspace.getAttribute('value');\n const updateHeight = () => {\n workspace.style.height = range.value + 'px';\n output.value = range.value;\n };\n range.addEventListener('input', updateHeight);\n example.querySelector('nve-button').addEventListener('click', () => {\n workspace.value = initialValue;\n range.value = '180';\n updateHeight();\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Keep tab titles readable in a narrow group with scrolling and keyboard selection.\n * @tags test-case\n */\nexport const TabOverflow = {\n render: () => html`\n <nve-workspace style=\"width:260px;height:260px\">\n ${[\n 'Editor',\n 'Preview',\n 'Terminal',\n 'Notes',\n 'Project outline',\n 'Recent activity',\n 'Task history',\n 'Search results'\n ].map(\n (title, index) => html`\n <nve-workspace-panel id=${`view-${index}`}>\n <nve-workspace-panel-header>${title}</nve-workspace-panel-header>\n <nve-workspace-panel-content>\n ${title === 'Editor' ? html`<nve-textarea><textarea aria-label=\"Editor\">Editor content</textarea></nve-textarea>` : `${title} content`}\n </nve-workspace-panel-content>\n </nve-workspace-panel>\n `\n )}\n </nve-workspace>\n `\n};\n\n/**\n * @summary Adjust spacing between groups with --gap. Zero joins the group frames.\n * @tags test-case\n */\nexport const Gap = {\n render: () => html`\n <div id=\"workspace-gap-example\" nve-layout=\"column gap:md\">\n <nve-range>\n <label>\n Gap:\n <output for=\"workspace-gap-range\">0</output>\n px\n </label>\n <input id=\"workspace-gap-range\" type=\"range\" min=\"0\" max=\"24\" value=\"0\" />\n </nve-range>\n <nve-workspace\n container=\"full\"\n resizable\n style=\"--gap:0px;height:360px\"\n value='{\"version\":1,\"closed\":[],\"root\":{\"type\":\"split\",\"axis\":\"horizontal\",\"weights\":[1,1],\"children\":[{\"type\":\"group\",\"panels\":[\"gap-editor\"],\"active\":\"gap-editor\"},{\"type\":\"group\",\"panels\":[\"gap-preview\"],\"active\":\"gap-preview\"}]}}'>\n <nve-workspace-panel id=\"gap-editor\">\n <nve-workspace-panel-header>Editor</nve-workspace-panel-header>\n <nve-workspace-panel-content>\n <nve-textarea><textarea aria-label=\"Editor\">Editor content</textarea></nve-textarea>\n </nve-workspace-panel-content>\n </nve-workspace-panel>\n <nve-workspace-panel id=\"gap-preview\">\n <nve-workspace-panel-header>Preview</nve-workspace-panel-header>\n <nve-workspace-panel-content>Preview content</nve-workspace-panel-content>\n </nve-workspace-panel>\n </nve-workspace>\n <script type=\"module\">\n const example = document.querySelector('#workspace-gap-example');\n const workspace = example.querySelector('nve-workspace');\n const range = example.querySelector('input');\n const output = example.querySelector('output');\n range.addEventListener('input', () => {\n workspace.style.setProperty('--gap', range.value + 'px');\n output.value = range.value;\n });\n </script>\n </div>\n `\n};\n"],"mappings":";AAGA,IAAAA,IAAS"}
|