@adea-ai/ui 0.63.4 → 0.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -0
- package/dist/NOTICE +81 -0
- package/dist/components/conversation/busy-send-button.d.ts +28 -0
- package/dist/components/conversation/busy-send-button.d.ts.map +1 -0
- package/dist/components/conversation/busy-send-button.js +184 -0
- package/dist/components/conversation/busy-send-button.js.map +1 -0
- package/dist/components/conversation/index.d.ts +1 -0
- package/dist/components/conversation/index.d.ts.map +1 -1
- package/dist/components/conversation/index.js +2 -1
- package/dist/components/layout/split-layout/drop.d.ts +13 -0
- package/dist/components/layout/split-layout/drop.d.ts.map +1 -0
- package/dist/components/layout/split-layout/drop.js +50 -0
- package/dist/components/layout/split-layout/drop.js.map +1 -0
- package/dist/components/layout/split-layout/geometry.d.ts +14 -0
- package/dist/components/layout/split-layout/geometry.d.ts.map +1 -0
- package/dist/components/layout/split-layout/geometry.js +44 -0
- package/dist/components/layout/split-layout/geometry.js.map +1 -0
- package/dist/components/layout/split-layout/index.d.ts +5 -0
- package/dist/components/layout/split-layout/index.d.ts.map +1 -0
- package/dist/components/layout/split-layout/index.js +4 -0
- package/dist/components/layout/split-layout/model.d.ts +51 -0
- package/dist/components/layout/split-layout/model.d.ts.map +1 -0
- package/dist/components/layout/split-layout/model.js +255 -0
- package/dist/components/layout/split-layout/model.js.map +1 -0
- package/dist/components/layout/split-layout/split-layout.d.ts +30 -0
- package/dist/components/layout/split-layout/split-layout.d.ts.map +1 -0
- package/dist/components/layout/split-layout/split-layout.js +312 -0
- package/dist/components/layout/split-layout/split-layout.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/lib/tokens.d.ts +3 -0
- package/dist/lib/tokens.d.ts.map +1 -1
- package/dist/lib/tokens.js +3 -0
- package/dist/lib/tokens.js.map +1 -1
- package/dist/r/conversation.json +7 -0
- package/dist/r/registry.json +48 -0
- package/dist/r/split-layout.json +41 -0
- package/dist/r/src/components/conversation/busy-send-button.tsx +161 -0
- package/dist/r/src/components/conversation/index.ts +1 -0
- package/dist/r/src/components/layout/split-layout/drop.ts +29 -0
- package/dist/r/src/components/layout/split-layout/geometry.ts +40 -0
- package/dist/r/src/components/layout/split-layout/index.ts +4 -0
- package/dist/r/src/components/layout/split-layout/model.ts +336 -0
- package/dist/r/src/components/layout/split-layout/split-layout.tsx +346 -0
- package/dist/r/src/lib/tokens.ts +3 -0
- package/dist/r/src/styles/theme.css +9 -0
- package/package.json +10 -2
- package/registry.json +48 -0
- package/src/components/conversation/busy-send-button.tsx +161 -0
- package/src/components/conversation/index.ts +1 -0
- package/src/components/layout/split-layout/drop.ts +29 -0
- package/src/components/layout/split-layout/geometry.ts +40 -0
- package/src/components/layout/split-layout/index.ts +4 -0
- package/src/components/layout/split-layout/model.ts +336 -0
- package/src/components/layout/split-layout/split-layout.tsx +346 -0
- package/src/index.ts +1 -0
- package/src/lib/tokens.ts +3 -0
- package/src/styles/theme.css +9 -0
package/README.md
CHANGED
|
@@ -153,6 +153,30 @@ The toolbar switches theme, accent, typeface and density live, which is the
|
|
|
153
153
|
fastest way to see how a component behaves across the catalogue rather than in
|
|
154
154
|
one theme.
|
|
155
155
|
|
|
156
|
+
## Busy composer action
|
|
157
|
+
|
|
158
|
+
Square icon controls use the control-height tokens through the Tailwind `--size`
|
|
159
|
+
mapping; `--spacing-control-*` remains the separate inline-padding ladder.
|
|
160
|
+
Text controls, icon buttons and toggles share the same height in both densities.
|
|
161
|
+
Dimensions remain rem-based and follow the consumer's root font size. The browser
|
|
162
|
+
geometry lane checks all six rungs, heights and padding under both themes/densities.
|
|
163
|
+
|
|
164
|
+
`BusySendButton` translates KiroCrew's split fire/mode-picker composition. Pass
|
|
165
|
+
controlled `mode`, `onModeChange` and `onFire`. `disabled` prevents firing while
|
|
166
|
+
leaving mode choice available before typing; `selectionDisabled` gates choosing.
|
|
167
|
+
Inject `unavailable` reasons for unsupported or unauthorized modes: rows remain
|
|
168
|
+
visible, and the selected action cannot fire. Supply `alternateActionHint` only
|
|
169
|
+
when the host implements the described keyboard chord. The component adds no
|
|
170
|
+
keyboard chord, preference storage, runtime command or queue. Persistence and
|
|
171
|
+
same-session preference synchronization remain application-owned.
|
|
172
|
+
|
|
173
|
+
Kobalte owns the menu and focus lifecycle. Its Tab prevention lacks row cycling,
|
|
174
|
+
so a menu-scoped donor translation cycles enabled rows without a document listener.
|
|
175
|
+
Stories cover before-typing, working,
|
|
176
|
+
unavailable and read-only states. `bun run test:components` checks the isolated
|
|
177
|
+
Solid composition headlessly in Chromium and WebKit. Full Chat composition,
|
|
178
|
+
packed distribution and real consumer/native acceptance remain separate gates.
|
|
179
|
+
|
|
156
180
|
## Transcript follow
|
|
157
181
|
|
|
158
182
|
`ConversationSurface` follows streamed text, earlier-row growth, turn collapse
|
|
@@ -194,6 +218,56 @@ acceptance and each application's mounted chat journey remain separate gates.
|
|
|
194
218
|
|
|
195
219
|
Apache-2.0.
|
|
196
220
|
|
|
221
|
+
## Binary layout model checkpoint
|
|
222
|
+
|
|
223
|
+
UI issue #22 extracts the existing attributed bb/Muxy Adea adaptation rather
|
|
224
|
+
than introducing another layout tree. `createLayoutState`, `splitPane`,
|
|
225
|
+
`movePane`, `closePane`, `undoClosePane`, `focusPane`, `swapPanes`,
|
|
226
|
+
`resizeSplit`, `normalizeLayout` and the reading-order helpers are pure.
|
|
227
|
+
Leaves extend `{kind: 'leaf', id: string}` with any host-owned payload. Closing
|
|
228
|
+
the last leaf calls an injected placeholder factory; it never selects a harness,
|
|
229
|
+
starts a terminal or deletes a project. Eight leaves/depth eight and 10–90%
|
|
230
|
+
ratios preserve the accepted contract. Construct or validate a tree before
|
|
231
|
+
editing it; the shared constructor validates visual structure and identities,
|
|
232
|
+
while applications still decode/scoped-persist preferences and retain unknown
|
|
233
|
+
future versions for recovery.
|
|
234
|
+
|
|
235
|
+
The model and maintained accessible renderer are implemented in this draft.
|
|
236
|
+
Stable content ownership and movement are exercised in component fixtures.
|
|
237
|
+
The packed renderer gate includes the UI #20 size-token correction and the host
|
|
238
|
+
presentation fixture. It checks the real package in compiled and Solid
|
|
239
|
+
conditions; complete shell composition, production adoption and release remain
|
|
240
|
+
required.
|
|
241
|
+
No persistent state, session services, native drag region or host framework is
|
|
242
|
+
imported into this model.
|
|
243
|
+
|
|
244
|
+
### Host pane presentation hooks
|
|
245
|
+
|
|
246
|
+
`SplitLayout` can keep its default pane header while allowing a host to supply
|
|
247
|
+
inline visible content with `renderPaneLabel`, opt pane regions into keyboard
|
|
248
|
+
Tab navigation with `paneTabIndex={0}`, and provide a domain-specific splitter
|
|
249
|
+
name with `labelForSeparator`. Pane regions remain programmatically focusable
|
|
250
|
+
by default (`paneTabIndex={-1}`), and separators keep their orientation-based
|
|
251
|
+
names unless the host supplies a label.
|
|
252
|
+
|
|
253
|
+
`renderPaneLabel` receives a stable `Accessor<L>` once for each leaf owner.
|
|
254
|
+
Read `leaf()` inside the returned JSX so Solid tracks payload changes while the
|
|
255
|
+
same pane owner is retained during split and move operations. This visible
|
|
256
|
+
header content does not define the region's accessible name or the close
|
|
257
|
+
button's name: both continue to come from `labelForLeaf`, so hosts should
|
|
258
|
+
provide an accessible domain label there as well.
|
|
259
|
+
|
|
260
|
+
The `HostPresentation` story shows a decorative icon and host title, keyboard
|
|
261
|
+
pane stops, and a workspace-specific separator name. A narrow-width component
|
|
262
|
+
fixture also checks that a long host title does not widen its pane header.
|
|
263
|
+
|
|
264
|
+
`bun run check:packed-layout` packs the real artifact, installs it in a disposable
|
|
265
|
+
consumer with peers omitted and scripts disabled, and exercises the direct model
|
|
266
|
+
subpath in native Node and the Solid source condition. It verifies zero runtime
|
|
267
|
+
imports and a 3 KiB gzip model budget (measured baseline: 2,455 bytes). This is
|
|
268
|
+
model-subpath evidence; it does not waive UI #16's package attribution/conditional
|
|
269
|
+
export corrections or the separate root compatibility gate.
|
|
270
|
+
|
|
197
271
|
### Controlled appearance editor
|
|
198
272
|
|
|
199
273
|
`AppearanceEditor` and `AppearancePopover` retain the accepted Zeron-derived
|
package/dist/NOTICE
CHANGED
|
@@ -49,6 +49,87 @@ Origin UI / coss (AGPL-3.0-or-later) was consulted for visual ideas only. No
|
|
|
49
49
|
code, class string, or asset from that project is reproduced here, because its
|
|
50
50
|
licence is incompatible with this distribution.
|
|
51
51
|
|
|
52
|
+
## Strict binary layout extracted from the accepted Adea donor port
|
|
53
|
+
|
|
54
|
+
`packages/ui/src/components/layout/split-layout/model.ts` is extracted from
|
|
55
|
+
Adea `packages/dev-view/src/layout/operations.ts` at
|
|
56
|
+
`0322ab09ff5e9775bfddc0bf2d81e1df436dbef7`, whose MIT portions substantially
|
|
57
|
+
translate bb `apps/app/src/lib/split-layout/ops.ts` at
|
|
58
|
+
`52a9256373d4d36f9b60e9e2a7f333464091a2ac` and Muxy
|
|
59
|
+
`Muxy/Models/Workspace/SplitNode.swift` at
|
|
60
|
+
`5c5be8697c57a2fe70cda97fdbaf7c912e2e31b6`.
|
|
61
|
+
|
|
62
|
+
Copyright (c) 2026 Michael Yong
|
|
63
|
+
Copyright (c) 2026 Muxy
|
|
64
|
+
|
|
65
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
66
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
67
|
+
in the Software without restriction, including without limitation the rights
|
|
68
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
69
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
70
|
+
furnished to do so, subject to the following conditions:
|
|
71
|
+
|
|
72
|
+
The above copyright notice and this permission notice shall be included in all
|
|
73
|
+
copies or substantial portions of the Software.
|
|
74
|
+
|
|
75
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
76
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
77
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
78
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
79
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
80
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
81
|
+
SOFTWARE.
|
|
82
|
+
|
|
83
|
+
The accepted strict binary representation, reading-order insertion, parent
|
|
84
|
+
collapse, exact leaf identity, resize/normalize, move-at-cap and undo semantics
|
|
85
|
+
are retained. Opaque host leaves replace private domain types and the host
|
|
86
|
+
supplies the last-pane placeholder. Construction validates visual identities
|
|
87
|
+
and structural bounds; application scope/persistence, thread/runtime identity,
|
|
88
|
+
harness launch and process authority are excluded. Nearest test behavior from
|
|
89
|
+
Adea `packages/dev-view/tests/layout.test.ts` and bb `ops.test.ts` is preserved
|
|
90
|
+
where it applies to the accepted binary model. The accessible renderer and
|
|
91
|
+
application adoption remain separate gates under UI issue #22.
|
|
92
|
+
|
|
93
|
+
### Binary frame renderer continuation
|
|
94
|
+
|
|
95
|
+
`geometry.ts` translates `areaFrames` from the pinned Muxy source above. Its
|
|
96
|
+
fractional frames, horizontal/vertical offsets and exact node references are
|
|
97
|
+
retained; ratio repair uses the accepted 0.1–0.9 range rather than Muxy's 0–1.
|
|
98
|
+
`split-layout.tsx` adapts the accepted Adea pane-header/close/focus behavior
|
|
99
|
+
through generic callbacks, stable keyed leaf owners and Corvu separators.
|
|
100
|
+
It excludes application commands, persistence, harness/thread authority and
|
|
101
|
+
manual pointer listeners. This renderer is independently written against the
|
|
102
|
+
accepted model; it is not a port of Muxy's native UI or an additional layout tree.
|
|
103
|
+
The MIT attribution and permission above cover the translated frame algorithm.
|
|
104
|
+
|
|
105
|
+
The pane-drag continuation retains Adea's nearest-edge placement ordering and
|
|
106
|
+
pane-title gesture, replacing plaintext leaf IDs and string casts with typed
|
|
107
|
+
intent, an instance-local active drag payload, and cancellation/removal checks.
|
|
108
|
+
Header action composition injects application keyboard controls without owning
|
|
109
|
+
shortcuts or domain transitions. No new upstream source or license is introduced.
|
|
110
|
+
|
|
111
|
+
Busy composer action translated from KiroCrew
|
|
112
|
+
--------------------------------------------
|
|
113
|
+
Original: website/src/components/BusySendButton.tsx
|
|
114
|
+
Also translated: website/src/hooks/useMenuKeyboard.ts (enabled-row Tab cycle)
|
|
115
|
+
Revision: 283e136c0f902e965a535a7c9548c57c7504fed0
|
|
116
|
+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
117
|
+
This product includes software developed at Amazon.com, Inc.
|
|
118
|
+
Apache License, Version 2.0 (see LICENSE).
|
|
119
|
+
Destination: packages/ui/src/components/conversation/busy-send-button.tsx
|
|
120
|
+
|
|
121
|
+
The split fire/mode-picker structure, descriptions, independent disabled-fire
|
|
122
|
+
state, selected radio treatment and conditional alternate-action hint are
|
|
123
|
+
substantially translated to Solid and the shared design system. Kobalte owns
|
|
124
|
+
portal positioning, arrow navigation, dismissal and focus restoration. Its
|
|
125
|
+
Tab prevention lacks row cycling, so the donor cycle is translated as a scoped
|
|
126
|
+
menu handler over enabled rows; no document listener or manual focus trap.
|
|
127
|
+
Donor per-slot storage/migration/broadcast, i18n/platform lookup, React runtime,
|
|
128
|
+
manual portal and document listeners are not copied. Applications inject mode,
|
|
129
|
+
action and unavailable reasons. No runtime queue or force-reset authority added.
|
|
130
|
+
Nearest tests: BusySendButton.menuKeyboard.test.tsx and
|
|
131
|
+
BusySendButton.slotScope.test.tsx; controlled mode replaces donor storage tests,
|
|
132
|
+
while keyboard/focus expectations are exercised in Chromium and WebKit.
|
|
52
133
|
## Plain transcript follow translated from KiroCrew
|
|
53
134
|
|
|
54
135
|
`packages/ui/src/components/conversation/scroll-follow-core.ts`,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type BusySendMode = 'steer' | 'queue';
|
|
2
|
+
export type BusySendButtonProps = {
|
|
3
|
+
mode: BusySendMode;
|
|
4
|
+
onModeChange: (mode: BusySendMode) => void;
|
|
5
|
+
/** Executes only the selected action. The host owns the draft and command. */
|
|
6
|
+
onFire: () => void;
|
|
7
|
+
/** An empty draft or pending delivery disables fire, but not choosing a mode. */
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
/** Disable mode selection when the host has no authority to change preferences. */
|
|
10
|
+
selectionDisabled?: boolean;
|
|
11
|
+
/** Host capability/authority failures: unavailable rows remain visible. */
|
|
12
|
+
unavailable?: Partial<Record<BusySendMode, string>>;
|
|
13
|
+
/** Supply only when the host implements this alternate-action keyboard chord. */
|
|
14
|
+
alternateActionHint?: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Kiro's split action/menu composition, with app-owned mode and availability.
|
|
18
|
+
* Picking a mode never fires it. Persistence, migration and same-session
|
|
19
|
+
* broadcasts belong to the consumer; this component has no storage or global listeners.
|
|
20
|
+
* Kobalte replaces the donor manual portal/positioning and document listeners:
|
|
21
|
+
* arrows wrap and selection/Escape return focus. Kobalte 0.13.14 prevents Tab
|
|
22
|
+
* without moving focus, so a menu-scoped translation of the donor Tab cycle
|
|
23
|
+
* fills that gap. It discovers enabled radio rows only; no document trap.
|
|
24
|
+
* No force-reset timer or runtime authority is translated from the adjacent
|
|
25
|
+
* donor stop flow.
|
|
26
|
+
*/
|
|
27
|
+
export declare function BusySendButton(props: BusySendButtonProps): import("solid-js").JSX.Element;
|
|
28
|
+
//# sourceMappingURL=busy-send-button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"busy-send-button.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/busy-send-button.tsx"],"names":[],"mappings":"AAmBA,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,OAAO,CAAA;AAC5C,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,YAAY,CAAA;IAClB,YAAY,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAA;IAC1C,8EAA8E;IAC9E,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,mFAAmF;IACnF,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,2EAA2E;IAC3E,WAAW,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAA;IACnD,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAA;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,kCA2GxD"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { Button } from "../ui/button/button.js";
|
|
2
|
+
import { ButtonGroup } from "../ui/button-group/button-group.js";
|
|
3
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger } from "../ui/dropdown-menu/dropdown-menu.js";
|
|
4
|
+
import { createComponent, insert, setAttribute, template } from "solid-js/web";
|
|
5
|
+
import { ArrowUpFromLine, ChevronDown, Target } from "lucide-solid";
|
|
6
|
+
import { For, Show, createUniqueId } from "solid-js";
|
|
7
|
+
//#region src/components/conversation/busy-send-button.tsx
|
|
8
|
+
var _tmpl$ = /*#__PURE__*/ template(`<p class="text-muted-foreground px-2 py-1 text-xs">`);
|
|
9
|
+
var _tmpl$2 = /*#__PURE__*/ template(`<div data-slot=busy-send-button class="flex w-fit flex-col gap-1">`);
|
|
10
|
+
var _tmpl$3 = /*#__PURE__*/ template(`<div class="flex min-w-0 flex-col gap-1"><span></span><span class="text-muted-foreground text-xs">`);
|
|
11
|
+
var _tmpl$4 = /*#__PURE__*/ template(`<span class="text-muted-foreground text-xs">`);
|
|
12
|
+
var _tmpl$5 = /*#__PURE__*/ template(`<p class="text-muted-foreground text-xs">`);
|
|
13
|
+
var modes = ["steer", "queue"];
|
|
14
|
+
var labels = {
|
|
15
|
+
steer: "Steer",
|
|
16
|
+
queue: "Queue"
|
|
17
|
+
};
|
|
18
|
+
var descriptions = {
|
|
19
|
+
steer: "Act on this right away",
|
|
20
|
+
queue: "Run after the current work finishes"
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Kiro's split action/menu composition, with app-owned mode and availability.
|
|
24
|
+
* Picking a mode never fires it. Persistence, migration and same-session
|
|
25
|
+
* broadcasts belong to the consumer; this component has no storage or global listeners.
|
|
26
|
+
* Kobalte replaces the donor manual portal/positioning and document listeners:
|
|
27
|
+
* arrows wrap and selection/Escape return focus. Kobalte 0.13.14 prevents Tab
|
|
28
|
+
* without moving focus, so a menu-scoped translation of the donor Tab cycle
|
|
29
|
+
* fills that gap. It discovers enabled radio rows only; no document trap.
|
|
30
|
+
* No force-reset timer or runtime authority is translated from the adjacent
|
|
31
|
+
* donor stop flow.
|
|
32
|
+
*/
|
|
33
|
+
function BusySendButton(props) {
|
|
34
|
+
const reasonId = createUniqueId();
|
|
35
|
+
const reason = () => props.unavailable?.[props.mode];
|
|
36
|
+
const variant = () => props.mode === "steer" ? "default" : "secondary";
|
|
37
|
+
return (() => {
|
|
38
|
+
var _el$ = _tmpl$2();
|
|
39
|
+
insert(_el$, createComponent(DropdownMenu, {
|
|
40
|
+
placement: "top-end",
|
|
41
|
+
modal: false,
|
|
42
|
+
get children() {
|
|
43
|
+
return [createComponent(ButtonGroup, {
|
|
44
|
+
label: "Send while busy",
|
|
45
|
+
get children() {
|
|
46
|
+
return [createComponent(Button, {
|
|
47
|
+
type: "button",
|
|
48
|
+
size: "icon-sm",
|
|
49
|
+
get variant() {
|
|
50
|
+
return variant();
|
|
51
|
+
},
|
|
52
|
+
get ["aria-label"]() {
|
|
53
|
+
return props.mode === "steer" ? "Steer" : "Queue message";
|
|
54
|
+
},
|
|
55
|
+
get ["aria-describedby"]() {
|
|
56
|
+
return reason() ? reasonId : void 0;
|
|
57
|
+
},
|
|
58
|
+
get disabled() {
|
|
59
|
+
return props.disabled || !!reason();
|
|
60
|
+
},
|
|
61
|
+
onClick: () => {
|
|
62
|
+
if (!props.disabled && !reason()) props.onFire();
|
|
63
|
+
},
|
|
64
|
+
get children() {
|
|
65
|
+
return createComponent(Show, {
|
|
66
|
+
get when() {
|
|
67
|
+
return props.mode === "steer";
|
|
68
|
+
},
|
|
69
|
+
get fallback() {
|
|
70
|
+
return createComponent(ArrowUpFromLine, {});
|
|
71
|
+
},
|
|
72
|
+
get children() {
|
|
73
|
+
return createComponent(Target, {});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}), createComponent(DropdownMenuTrigger, {
|
|
78
|
+
as: Button,
|
|
79
|
+
type: "button",
|
|
80
|
+
size: "icon-sm",
|
|
81
|
+
get variant() {
|
|
82
|
+
return variant();
|
|
83
|
+
},
|
|
84
|
+
"aria-label": "Send options",
|
|
85
|
+
get disabled() {
|
|
86
|
+
return props.selectionDisabled;
|
|
87
|
+
},
|
|
88
|
+
get children() {
|
|
89
|
+
return createComponent(ChevronDown, {});
|
|
90
|
+
}
|
|
91
|
+
})];
|
|
92
|
+
}
|
|
93
|
+
}), createComponent(DropdownMenuContent, {
|
|
94
|
+
hideArrow: true,
|
|
95
|
+
get children() {
|
|
96
|
+
return [createComponent(DropdownMenuRadioGroup, {
|
|
97
|
+
"on:keydown": (event) => {
|
|
98
|
+
if (event.key !== "Tab" || event.isComposing || !(event.currentTarget instanceof HTMLElement)) return;
|
|
99
|
+
const rows = Array.from(event.currentTarget.querySelectorAll("[role=\"menuitemradio\"]:not([aria-disabled=\"true\"])"));
|
|
100
|
+
if (!rows.length) return;
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
event.stopPropagation();
|
|
103
|
+
const active = document.activeElement;
|
|
104
|
+
const index = active instanceof HTMLElement ? rows.indexOf(active) : -1;
|
|
105
|
+
rows[index < 0 ? event.shiftKey ? rows.length - 1 : 0 : (index + (event.shiftKey ? -1 : 1) + rows.length) % rows.length]?.focus();
|
|
106
|
+
},
|
|
107
|
+
get value() {
|
|
108
|
+
return props.mode;
|
|
109
|
+
},
|
|
110
|
+
onChange: (value) => {
|
|
111
|
+
if ((value === "steer" || value === "queue") && !props.selectionDisabled && !props.unavailable?.[value]) props.onModeChange(value);
|
|
112
|
+
},
|
|
113
|
+
get children() {
|
|
114
|
+
return createComponent(For, {
|
|
115
|
+
each: modes,
|
|
116
|
+
children: (mode) => createComponent(DropdownMenuRadioItem, {
|
|
117
|
+
value: mode,
|
|
118
|
+
closeOnSelect: true,
|
|
119
|
+
get disabled() {
|
|
120
|
+
return props.selectionDisabled || !!props.unavailable?.[mode];
|
|
121
|
+
},
|
|
122
|
+
get children() {
|
|
123
|
+
return [createComponent(Show, {
|
|
124
|
+
when: mode === "steer",
|
|
125
|
+
get fallback() {
|
|
126
|
+
return createComponent(ArrowUpFromLine, {});
|
|
127
|
+
},
|
|
128
|
+
get children() {
|
|
129
|
+
return createComponent(Target, {});
|
|
130
|
+
}
|
|
131
|
+
}), (() => {
|
|
132
|
+
var _el$3 = _tmpl$3(), _el$4 = _el$3.firstChild, _el$5 = _el$4.nextSibling;
|
|
133
|
+
insert(_el$4, () => labels[mode]);
|
|
134
|
+
insert(_el$5, () => descriptions[mode]);
|
|
135
|
+
insert(_el$3, createComponent(Show, {
|
|
136
|
+
get when() {
|
|
137
|
+
return props.unavailable?.[mode];
|
|
138
|
+
},
|
|
139
|
+
children: (message) => (() => {
|
|
140
|
+
var _el$6 = _tmpl$4();
|
|
141
|
+
insert(_el$6, message);
|
|
142
|
+
return _el$6;
|
|
143
|
+
})()
|
|
144
|
+
}), null);
|
|
145
|
+
return _el$3;
|
|
146
|
+
})()];
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}), createComponent(Show, {
|
|
152
|
+
get when() {
|
|
153
|
+
return props.alternateActionHint;
|
|
154
|
+
},
|
|
155
|
+
get children() {
|
|
156
|
+
return [createComponent(DropdownMenuSeparator, {}), (() => {
|
|
157
|
+
var _el$2 = _tmpl$();
|
|
158
|
+
insert(_el$2, () => props.alternateActionHint);
|
|
159
|
+
return _el$2;
|
|
160
|
+
})()];
|
|
161
|
+
}
|
|
162
|
+
})];
|
|
163
|
+
}
|
|
164
|
+
})];
|
|
165
|
+
}
|
|
166
|
+
}), null);
|
|
167
|
+
insert(_el$, createComponent(Show, {
|
|
168
|
+
get when() {
|
|
169
|
+
return reason();
|
|
170
|
+
},
|
|
171
|
+
children: (message) => (() => {
|
|
172
|
+
var _el$7 = _tmpl$5();
|
|
173
|
+
setAttribute(_el$7, "id", reasonId);
|
|
174
|
+
insert(_el$7, message);
|
|
175
|
+
return _el$7;
|
|
176
|
+
})()
|
|
177
|
+
}), null);
|
|
178
|
+
return _el$;
|
|
179
|
+
})();
|
|
180
|
+
}
|
|
181
|
+
//#endregion
|
|
182
|
+
export { BusySendButton };
|
|
183
|
+
|
|
184
|
+
//# sourceMappingURL=busy-send-button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"busy-send-button.js","names":["ArrowUpFromLine","ChevronDown","Target","For","Show","createUniqueId","Button","ButtonGroup","DropdownMenu","DropdownMenuContent","DropdownMenuRadioGroup","DropdownMenuRadioItem","DropdownMenuSeparator","DropdownMenuTrigger","BusySendMode","BusySendButtonProps","mode","onModeChange","onFire","disabled","selectionDisabled","unavailable","Partial","Record","alternateActionHint","modes","labels","steer","queue","descriptions","BusySendButton","props","reasonId","reason","variant","const","_el$","_tmpl$2","_$insert","_$createComponent","placement","modal","children","label","type","size","aria-label","aria-describedby","undefined","onClick","when","fallback","as","hideArrow","on:keydown","event","KeyboardEvent","key","isComposing","currentTarget","HTMLElement","rows","Array","from","querySelectorAll","length","preventDefault","stopPropagation","active","document","activeElement","index","indexOf","next","shiftKey","focus","value","onChange","each","closeOnSelect","_el$3","_tmpl$3","_el$4","firstChild","_el$5","nextSibling","message","_el$6","_tmpl$4","_el$2","_tmpl$","_el$7","_tmpl$5","_$setAttribute","_$createComponent"],"sources":["../../../src/components/conversation/busy-send-button.tsx"],"sourcesContent":["/*\n * Substantially translated from KiroCrew website/src/components/BusySendButton.tsx\n * at 283e136c0f902e965a535a7c9548c57c7504fed0.\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * Licensed under Apache-2.0; see LICENSE and NOTICE.\n */\nimport { ArrowUpFromLine, ChevronDown, Target } from 'lucide-solid'\nimport { For, Show, createUniqueId } from 'solid-js'\nimport { Button } from '../ui/button/button'\nimport { ButtonGroup } from '../ui/button-group/button-group'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu/dropdown-menu'\n\nexport type BusySendMode = 'steer' | 'queue'\nexport type BusySendButtonProps = {\n mode: BusySendMode\n onModeChange: (mode: BusySendMode) => void\n /** Executes only the selected action. The host owns the draft and command. */\n onFire: () => void\n /** An empty draft or pending delivery disables fire, but not choosing a mode. */\n disabled?: boolean\n /** Disable mode selection when the host has no authority to change preferences. */\n selectionDisabled?: boolean\n /** Host capability/authority failures: unavailable rows remain visible. */\n unavailable?: Partial<Record<BusySendMode, string>>\n /** Supply only when the host implements this alternate-action keyboard chord. */\n alternateActionHint?: string\n}\n\nconst modes: BusySendMode[] = ['steer', 'queue']\nconst labels = { steer: 'Steer', queue: 'Queue' }\nconst descriptions = {\n steer: 'Act on this right away',\n queue: 'Run after the current work finishes',\n}\n\n/**\n * Kiro's split action/menu composition, with app-owned mode and availability.\n * Picking a mode never fires it. Persistence, migration and same-session\n * broadcasts belong to the consumer; this component has no storage or global listeners.\n * Kobalte replaces the donor manual portal/positioning and document listeners:\n * arrows wrap and selection/Escape return focus. Kobalte 0.13.14 prevents Tab\n * without moving focus, so a menu-scoped translation of the donor Tab cycle\n * fills that gap. It discovers enabled radio rows only; no document trap.\n * No force-reset timer or runtime authority is translated from the adjacent\n * donor stop flow.\n */\nexport function BusySendButton(props: BusySendButtonProps) {\n const reasonId = createUniqueId()\n const reason = () => props.unavailable?.[props.mode]\n const variant = () => (props.mode === 'steer' ? ('default' as const) : ('secondary' as const))\n return (\n <div data-slot=\"busy-send-button\" class=\"flex w-fit flex-col gap-1\">\n <DropdownMenu placement=\"top-end\" modal={false}>\n <ButtonGroup label=\"Send while busy\">\n <Button\n type=\"button\"\n size=\"icon-sm\"\n variant={variant()}\n aria-label={props.mode === 'steer' ? 'Steer' : 'Queue message'}\n aria-describedby={reason() ? reasonId : undefined}\n disabled={props.disabled || !!reason()}\n onClick={() => {\n if (!props.disabled && !reason()) props.onFire()\n }}\n >\n <Show when={props.mode === 'steer'} fallback={<ArrowUpFromLine />}>\n <Target />\n </Show>\n </Button>\n <DropdownMenuTrigger\n as={Button}\n type=\"button\"\n size=\"icon-sm\"\n variant={variant()}\n aria-label=\"Send options\"\n disabled={props.selectionDisabled}\n >\n <ChevronDown />\n </DropdownMenuTrigger>\n </ButtonGroup>\n <DropdownMenuContent hideArrow>\n <DropdownMenuRadioGroup\n on:keydown={(event: KeyboardEvent) => {\n if (\n event.key !== 'Tab' ||\n event.isComposing ||\n !(event.currentTarget instanceof HTMLElement)\n )\n return\n const rows = Array.from(\n event.currentTarget.querySelectorAll<HTMLElement>(\n '[role=\"menuitemradio\"]:not([aria-disabled=\"true\"])'\n )\n )\n if (!rows.length) return\n event.preventDefault()\n event.stopPropagation()\n const active = document.activeElement\n const index = active instanceof HTMLElement ? rows.indexOf(active) : -1\n const next =\n index < 0\n ? event.shiftKey\n ? rows.length - 1\n : 0\n : (index + (event.shiftKey ? -1 : 1) + rows.length) % rows.length\n rows[next]?.focus()\n }}\n value={props.mode}\n onChange={(value) => {\n if (\n (value === 'steer' || value === 'queue') &&\n !props.selectionDisabled &&\n !props.unavailable?.[value]\n )\n props.onModeChange(value)\n }}\n >\n <For each={modes}>\n {(mode) => (\n <DropdownMenuRadioItem\n value={mode}\n closeOnSelect\n disabled={props.selectionDisabled || !!props.unavailable?.[mode]}\n >\n <Show when={mode === 'steer'} fallback={<ArrowUpFromLine />}>\n <Target />\n </Show>\n <div class=\"flex min-w-0 flex-col gap-1\">\n <span>{labels[mode]}</span>\n <span class=\"text-muted-foreground text-xs\">{descriptions[mode]}</span>\n <Show when={props.unavailable?.[mode]}>\n {(message) => <span class=\"text-muted-foreground text-xs\">{message()}</span>}\n </Show>\n </div>\n </DropdownMenuRadioItem>\n )}\n </For>\n </DropdownMenuRadioGroup>\n <Show when={props.alternateActionHint}>\n <DropdownMenuSeparator />\n <p class=\"text-muted-foreground px-2 py-1 text-xs\">{props.alternateActionHint}</p>\n </Show>\n </DropdownMenuContent>\n </DropdownMenu>\n <Show when={reason()}>\n {(message) => (\n <p id={reasonId} class=\"text-muted-foreground text-xs\">\n {message()}\n </p>\n )}\n </Show>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { BusySendButton, type BusySendMode, type BusySendButtonProps } from './busy-send-button';
|
|
1
2
|
export { ConversationAvatar, type ConversationAvatarKind, type ConversationAvatarProps, } from './conversation-avatar';
|
|
2
3
|
export { ConversationSurface, type ConversationSurfaceProps } from './conversation-surface';
|
|
3
4
|
export { ComposerAttachmentButton, ComposerHint, MessageComposer, type MessageComposerProps, } from './message-composer';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,mBAAmB,EAAE,KAAK,wBAAwB,EAAE,MAAM,wBAAwB,CAAA;AAC3F,OAAO,EACL,wBAAwB,EACxB,YAAY,EACZ,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,cAAc,EACd,WAAW,EACX,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAChG,OAAO,EACL,kBAAkB,EAClB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,mBAAmB,EAAE,KAAK,wBAAwB,EAAE,MAAM,wBAAwB,CAAA;AAC3F,OAAO,EACL,wBAAwB,EACxB,YAAY,EACZ,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,cAAc,EACd,WAAW,EACX,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { BusySendButton } from "./busy-send-button.js";
|
|
1
2
|
import { ConversationAvatar } from "./conversation-avatar.js";
|
|
2
3
|
import { ConversationSurface } from "./conversation-surface.js";
|
|
3
4
|
import { ComposerAttachmentButton, ComposerHint, MessageComposer } from "./message-composer.js";
|
|
4
5
|
import { MessageBody, MessageDayDivider, MessageGroup, MessageRow } from "./message-row.js";
|
|
5
6
|
import { AttachmentCard, ThreadPanel } from "./thread-panel.js";
|
|
6
|
-
export { AttachmentCard, ComposerAttachmentButton, ComposerHint, ConversationAvatar, ConversationSurface, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, ThreadPanel };
|
|
7
|
+
export { AttachmentCard, BusySendButton, ComposerAttachmentButton, ComposerHint, ConversationAvatar, ConversationSurface, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, ThreadPanel };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SplitLayoutBranch } from './model';
|
|
2
|
+
export type PaneDropIntent = {
|
|
3
|
+
direction: SplitLayoutBranch['direction'];
|
|
4
|
+
placement: 'before' | 'after';
|
|
5
|
+
};
|
|
6
|
+
/** Accepted Adea closest-edge intent; invalid/outside geometry cannot authorize a move. */
|
|
7
|
+
export declare function paneDropIntent(clientX: number, clientY: number, rect: {
|
|
8
|
+
left: number;
|
|
9
|
+
top: number;
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
}): PaneDropIntent | undefined;
|
|
13
|
+
//# sourceMappingURL=drop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drop.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/split-layout/drop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAChD,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,iBAAiB,CAAC,WAAW,CAAC,CAAA;IACzC,SAAS,EAAE,QAAQ,GAAG,OAAO,CAAA;CAC9B,CAAA;AACD,2FAA2F;AAC3F,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACjE,cAAc,GAAG,SAAS,CAkB5B"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//#region src/components/layout/split-layout/drop.ts
|
|
2
|
+
/** Accepted Adea closest-edge intent; invalid/outside geometry cannot authorize a move. */
|
|
3
|
+
function paneDropIntent(clientX, clientY, rect) {
|
|
4
|
+
const { left, top, width, height } = rect;
|
|
5
|
+
if (![
|
|
6
|
+
clientX,
|
|
7
|
+
clientY,
|
|
8
|
+
left,
|
|
9
|
+
top,
|
|
10
|
+
width,
|
|
11
|
+
height
|
|
12
|
+
].every(Number.isFinite) || width <= 0 || height <= 0) return;
|
|
13
|
+
const x = clientX - left;
|
|
14
|
+
const y = clientY - top;
|
|
15
|
+
if (x < 0 || y < 0 || x > width || y > height) return;
|
|
16
|
+
return [
|
|
17
|
+
{
|
|
18
|
+
distance: x,
|
|
19
|
+
intent: {
|
|
20
|
+
direction: "row",
|
|
21
|
+
placement: "before"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
distance: width - x,
|
|
26
|
+
intent: {
|
|
27
|
+
direction: "row",
|
|
28
|
+
placement: "after"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
distance: y,
|
|
33
|
+
intent: {
|
|
34
|
+
direction: "column",
|
|
35
|
+
placement: "before"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
distance: height - y,
|
|
40
|
+
intent: {
|
|
41
|
+
direction: "column",
|
|
42
|
+
placement: "after"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
].reduce((best, next) => next.distance < best.distance ? next : best).intent;
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { paneDropIntent };
|
|
49
|
+
|
|
50
|
+
//# sourceMappingURL=drop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drop.js","names":[],"sources":["../../../../src/components/layout/split-layout/drop.ts"],"sourcesContent":["import type { SplitLayoutBranch } from './model'\nexport type PaneDropIntent = {\n direction: SplitLayoutBranch['direction']\n placement: 'before' | 'after'\n}\n/** Accepted Adea closest-edge intent; invalid/outside geometry cannot authorize a move. */\nexport function paneDropIntent(\n clientX: number,\n clientY: number,\n rect: { left: number; top: number; width: number; height: number }\n): PaneDropIntent | undefined {\n const { left, top, width, height } = rect\n if (\n ![clientX, clientY, left, top, width, height].every(Number.isFinite) ||\n width <= 0 ||\n height <= 0\n )\n return\n const x = clientX - left\n const y = clientY - top\n if (x < 0 || y < 0 || x > width || y > height) return\n const candidates: { distance: number; intent: PaneDropIntent }[] = [\n { distance: x, intent: { direction: 'row', placement: 'before' } },\n { distance: width - x, intent: { direction: 'row', placement: 'after' } },\n { distance: y, intent: { direction: 'column', placement: 'before' } },\n { distance: height - y, intent: { direction: 'column', placement: 'after' } },\n ]\n return candidates.reduce((best, next) => (next.distance < best.distance ? next : best)).intent\n}\n"],"mappings":";;AAMA,SAAgB,eACd,SACA,SACA,MAC4B;CAC5B,MAAM,EAAE,MAAM,KAAK,OAAO,WAAW;CACrC,IACE,CAAC;EAAC;EAAS;EAAS;EAAM;EAAK;EAAO;CAAM,CAAC,CAAC,MAAM,OAAO,QAAQ,KACnE,SAAS,KACT,UAAU,GAEV;CACF,MAAM,IAAI,UAAU;CACpB,MAAM,IAAI,UAAU;CACpB,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,SAAS,IAAI,QAAQ;CAO/C,OAAO;EALL;GAAE,UAAU;GAAG,QAAQ;IAAE,WAAW;IAAO,WAAW;GAAS;EAAE;EACjE;GAAE,UAAU,QAAQ;GAAG,QAAQ;IAAE,WAAW;IAAO,WAAW;GAAQ;EAAE;EACxE;GAAE,UAAU;GAAG,QAAQ;IAAE,WAAW;IAAU,WAAW;GAAS;EAAE;EACpE;GAAE,UAAU,SAAS;GAAG,QAAQ;IAAE,WAAW;IAAU,WAAW;GAAQ;EAAE;CAEvE,CAAA,CAAW,QAAQ,MAAM,SAAU,KAAK,WAAW,KAAK,WAAW,OAAO,IAAK,CAAC,CAAC;AAC1F"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type SplitLayoutLeaf, type SplitLayoutNode } from './model';
|
|
2
|
+
export type LayoutRect = Readonly<{
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}>;
|
|
8
|
+
export type LayoutFrame<L extends SplitLayoutLeaf = SplitLayoutLeaf> = Readonly<{
|
|
9
|
+
node: SplitLayoutNode<L>;
|
|
10
|
+
rect: LayoutRect;
|
|
11
|
+
}>;
|
|
12
|
+
/** Stable leaf DOM can use these fractions without being reparented into a changing nested tree. */
|
|
13
|
+
export declare function computeLayoutFrames<L extends SplitLayoutLeaf>(node: SplitLayoutNode<L>): ReadonlyMap<string, LayoutFrame<L>>;
|
|
14
|
+
//# sourceMappingURL=geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/split-layout/geometry.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,eAAe,EACrB,MAAM,SAAS,CAAA;AAChB,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAC1F,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe,IAAI,QAAQ,CAAC;IAC9E,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,CAAA;IACxB,IAAI,EAAE,UAAU,CAAA;CACjB,CAAC,CAAA;AACF,oGAAoG;AACpG,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,eAAe,EAC3D,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,GACvB,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAoBrC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { MAX_SPLIT_RATIO, MIN_SPLIT_RATIO } from "./model.js";
|
|
2
|
+
//#region src/components/layout/split-layout/geometry.ts
|
|
3
|
+
/** Stable leaf DOM can use these fractions without being reparented into a changing nested tree. */
|
|
4
|
+
function computeLayoutFrames(node) {
|
|
5
|
+
const frames = /* @__PURE__ */ new Map();
|
|
6
|
+
const visit = (current, rect) => {
|
|
7
|
+
frames.set(current.id, {
|
|
8
|
+
node: current,
|
|
9
|
+
rect
|
|
10
|
+
});
|
|
11
|
+
if (current.kind === "leaf") return;
|
|
12
|
+
const ratio = Number.isFinite(current.ratio) ? Math.min(MAX_SPLIT_RATIO, Math.max(MIN_SPLIT_RATIO, current.ratio)) : .5;
|
|
13
|
+
const row = current.direction === "row";
|
|
14
|
+
const first = row ? {
|
|
15
|
+
...rect,
|
|
16
|
+
width: rect.width * ratio
|
|
17
|
+
} : {
|
|
18
|
+
...rect,
|
|
19
|
+
height: rect.height * ratio
|
|
20
|
+
};
|
|
21
|
+
const second = row ? {
|
|
22
|
+
...rect,
|
|
23
|
+
x: rect.x + first.width,
|
|
24
|
+
width: rect.width - first.width
|
|
25
|
+
} : {
|
|
26
|
+
...rect,
|
|
27
|
+
y: rect.y + first.height,
|
|
28
|
+
height: rect.height - first.height
|
|
29
|
+
};
|
|
30
|
+
visit(current.children[0], first);
|
|
31
|
+
visit(current.children[1], second);
|
|
32
|
+
};
|
|
33
|
+
visit(node, {
|
|
34
|
+
x: 0,
|
|
35
|
+
y: 0,
|
|
36
|
+
width: 1,
|
|
37
|
+
height: 1
|
|
38
|
+
});
|
|
39
|
+
return frames;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { computeLayoutFrames };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=geometry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.js","names":[],"sources":["../../../../src/components/layout/split-layout/geometry.ts"],"sourcesContent":["/*\n * Translated from Muxy/Models/Workspace/SplitNode.swift areaFrames at\n * 5c5be8697c57a2fe70cda97fdbaf7c912e2e31b6.\n * Copyright (c) 2026 Muxy. SPDX-License-Identifier: MIT. See NOTICE.\n */\nimport {\n MAX_SPLIT_RATIO,\n MIN_SPLIT_RATIO,\n type SplitLayoutLeaf,\n type SplitLayoutNode,\n} from './model'\nexport type LayoutRect = Readonly<{ x: number; y: number; width: number; height: number }>\nexport type LayoutFrame<L extends SplitLayoutLeaf = SplitLayoutLeaf> = Readonly<{\n node: SplitLayoutNode<L>\n rect: LayoutRect\n}>\n/** Stable leaf DOM can use these fractions without being reparented into a changing nested tree. */\nexport function computeLayoutFrames<L extends SplitLayoutLeaf>(\n node: SplitLayoutNode<L>\n): ReadonlyMap<string, LayoutFrame<L>> {\n const frames = new Map<string, LayoutFrame<L>>()\n const visit = (current: SplitLayoutNode<L>, rect: LayoutRect) => {\n frames.set(current.id, { node: current, rect })\n if (current.kind === 'leaf') return\n const ratio = Number.isFinite(current.ratio)\n ? Math.min(MAX_SPLIT_RATIO, Math.max(MIN_SPLIT_RATIO, current.ratio))\n : 0.5\n const row = current.direction === 'row'\n const first = row\n ? { ...rect, width: rect.width * ratio }\n : { ...rect, height: rect.height * ratio }\n const second = row\n ? { ...rect, x: rect.x + first.width, width: rect.width - first.width }\n : { ...rect, y: rect.y + first.height, height: rect.height - first.height }\n visit(current.children[0], first)\n visit(current.children[1], second)\n }\n visit(node, { x: 0, y: 0, width: 1, height: 1 })\n return frames\n}\n"],"mappings":";;;AAiBA,SAAgB,oBACd,MACqC;CACrC,MAAM,yBAAS,IAAI,IAA4B;CAC/C,MAAM,SAAS,SAA6B,SAAqB;EAC/D,OAAO,IAAI,QAAQ,IAAI;GAAE,MAAM;GAAS;EAAK,CAAC;EAC9C,IAAI,QAAQ,SAAS,QAAQ;EAC7B,MAAM,QAAQ,OAAO,SAAS,QAAQ,KAAK,IACvC,KAAK,IAAI,iBAAiB,KAAK,IAAI,iBAAiB,QAAQ,KAAK,CAAC,IAClE;EACJ,MAAM,MAAM,QAAQ,cAAc;EAClC,MAAM,QAAQ,MACV;GAAE,GAAG;GAAM,OAAO,KAAK,QAAQ;EAAM,IACrC;GAAE,GAAG;GAAM,QAAQ,KAAK,SAAS;EAAM;EAC3C,MAAM,SAAS,MACX;GAAE,GAAG;GAAM,GAAG,KAAK,IAAI,MAAM;GAAO,OAAO,KAAK,QAAQ,MAAM;EAAM,IACpE;GAAE,GAAG;GAAM,GAAG,KAAK,IAAI,MAAM;GAAQ,QAAQ,KAAK,SAAS,MAAM;EAAO;EAC5E,MAAM,QAAQ,SAAS,IAAI,KAAK;EAChC,MAAM,QAAQ,SAAS,IAAI,MAAM;CACnC;CACA,MAAM,MAAM;EAAE,GAAG;EAAG,GAAG;EAAG,OAAO;EAAG,QAAQ;CAAE,CAAC;CAC/C,OAAO;AACT"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/split-layout/index.ts"],"names":[],"mappings":"AAAA,yGAAyG;AACzG,cAAc,SAAS,CAAA;AACvB,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, closePane, countLeaves, createLayoutState, focusPane, layoutDepth, listLeaves, movePane, neighborLeaf, normalizeLayout, resizeSplit, splitPane, swapPanes, undoClosePane } from "./model.js";
|
|
2
|
+
import { computeLayoutFrames } from "./geometry.js";
|
|
3
|
+
import { SplitLayout } from "./split-layout.js";
|
|
4
|
+
export { MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, SplitLayout, closePane, computeLayoutFrames, countLeaves, createLayoutState, focusPane, layoutDepth, listLeaves, movePane, neighborLeaf, normalizeLayout, resizeSplit, splitPane, swapPanes, undoClosePane };
|