@adea-ai/ui 0.104.2 → 0.105.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 +11 -0
- package/dist/components/layout/split-layout/geometry.js +1 -1
- package/dist/components/layout/split-layout/index.js +2 -1
- package/dist/components/layout/split-layout/model.d.ts +2 -20
- package/dist/components/layout/split-layout/model.d.ts.map +1 -1
- package/dist/components/layout/split-layout/model.js +2 -14
- package/dist/components/layout/split-layout/model.js.map +1 -1
- package/dist/components/layout/split-layout/split-layout.js +1 -1
- package/dist/components/layout/split-layout/tree.d.ts +21 -0
- package/dist/components/layout/split-layout/tree.d.ts.map +1 -0
- package/dist/components/layout/split-layout/tree.js +18 -0
- package/dist/components/layout/split-layout/tree.js.map +1 -0
- package/dist/components/ui/kbd/index.d.ts +1 -1
- package/dist/components/ui/kbd/index.d.ts.map +1 -1
- package/dist/components/ui/kbd/index.js +2 -2
- package/dist/components/ui/kbd/kbd.d.ts +40 -2
- package/dist/components/ui/kbd/kbd.d.ts.map +1 -1
- package/dist/components/ui/kbd/kbd.js +74 -7
- package/dist/components/ui/kbd/kbd.js.map +1 -1
- package/dist/index.js +4 -3
- package/dist/r/about-dialog.json +1 -1
- package/dist/r/accordion.json +1 -1
- package/dist/r/account-menu.json +1 -1
- package/dist/r/alert.json +1 -1
- package/dist/r/appearance-editor.json +2 -2
- package/dist/r/breadcrumb.json +1 -1
- package/dist/r/calendar.json +1 -1
- package/dist/r/carousel.json +1 -1
- package/dist/r/catalog-browser.json +1 -1
- package/dist/r/checkbox.json +1 -1
- package/dist/r/code-block.json +1 -1
- package/dist/r/combobox.json +1 -1
- package/dist/r/command.json +1 -1
- package/dist/r/context-menu.json +1 -1
- package/dist/r/conversation.json +1 -1
- package/dist/r/detail-panel.json +1 -1
- package/dist/r/dialog.json +1 -1
- package/dist/r/dropdown-menu.json +1 -1
- package/dist/r/empty.json +1 -1
- package/dist/r/floating-preview.json +1 -1
- package/dist/r/help-center.json +1 -1
- package/dist/r/lib.json +1 -1
- package/dist/r/menubar.json +1 -1
- package/dist/r/native-select.json +1 -1
- package/dist/r/navigation-menu.json +1 -1
- package/dist/r/pagination.json +1 -1
- package/dist/r/radio-group.json +1 -1
- package/dist/r/registry.json +47 -42
- package/dist/r/resizable.json +1 -1
- package/dist/r/scene-controls.json +1 -1
- package/dist/r/select.json +1 -1
- package/dist/r/sheet.json +1 -1
- package/dist/r/sidebar-nav.json +1 -1
- package/dist/r/spinner.json +1 -1
- package/dist/r/split-layout.json +6 -1
- package/dist/r/src/components/layout/split-layout/model.ts +11 -30
- package/dist/r/src/components/layout/split-layout/tree.ts +51 -0
- package/dist/r/src/components/ui/kbd/index.ts +10 -1
- package/dist/r/src/components/ui/kbd/kbd.tsx +77 -14
- package/dist/r/stat.json +1 -1
- package/dist/r/theming.json +2 -2
- package/dist/r/toast.json +1 -1
- package/dist/r/top-bar.json +1 -1
- package/dist/r/tree.json +1 -1
- package/dist/r/update-dialog.json +1 -1
- package/package.json +13 -7
- package/registry.json +47 -42
- package/src/components/layout/split-layout/model.ts +11 -30
- package/src/components/layout/split-layout/tree.ts +51 -0
- package/src/components/ui/kbd/index.ts +10 -1
- package/src/components/ui/kbd/kbd.tsx +77 -14
package/README.md
CHANGED
|
@@ -829,3 +829,14 @@ existing provider-bound API.
|
|
|
829
829
|
Catalog detail summaries place actions and feedback beneath identity on narrow
|
|
830
830
|
screens, preserving readable title/description flow. Grouped field sections keep
|
|
831
831
|
their content at the top while sharing the outline and dividers.
|
|
832
|
+
|
|
833
|
+
### Small split-layout tree imports
|
|
834
|
+
|
|
835
|
+
Scoped persistence decoders can import `MAX_LAYOUT_LEAVES`, `MAX_LAYOUT_DEPTH`,
|
|
836
|
+
`MIN_SPLIT_RATIO`, `MAX_SPLIT_RATIO`, `listLeaves`, `countLeaves`, `layoutDepth`,
|
|
837
|
+
and the opaque tree types from
|
|
838
|
+
`@adea-ai/ui/components/layout/split-layout/tree`. This read-only entry has no
|
|
839
|
+
UI runtime, renderer, or pane-editing dependencies. The existing `/model` entry
|
|
840
|
+
re-exports the same functions and types for compatibility. Use `/model` for
|
|
841
|
+
split, close, move, resize, and undo operations; use the component entry when
|
|
842
|
+
rendering the layout.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MAX_SPLIT_RATIO, MIN_SPLIT_RATIO } from "./
|
|
1
|
+
import { MAX_SPLIT_RATIO, MIN_SPLIT_RATIO } from "./tree.js";
|
|
2
2
|
//#region src/components/layout/split-layout/geometry.ts
|
|
3
3
|
/** Stable leaf DOM can use these fractions without being reparented into a changing nested tree. */
|
|
4
4
|
function computeLayoutFrames(node) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO,
|
|
1
|
+
import { MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, countLeaves, layoutDepth, listLeaves } from "./tree.js";
|
|
2
|
+
import { closePane, createLayoutState, focusPane, movePane, neighborLeaf, normalizeLayout, resizeSplit, splitPane, swapPanes, undoClosePane } from "./model.js";
|
|
2
3
|
import { computeLayoutFrames } from "./geometry.js";
|
|
3
4
|
import { SplitLayout } from "./split-layout.js";
|
|
4
5
|
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 };
|
|
@@ -1,20 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
kind: 'leaf';
|
|
4
|
-
id: string;
|
|
5
|
-
}>;
|
|
6
|
-
export type SplitLayoutBranch<L extends SplitLayoutLeaf = SplitLayoutLeaf> = Readonly<{
|
|
7
|
-
kind: 'split';
|
|
8
|
-
id: string;
|
|
9
|
-
direction: 'row' | 'column';
|
|
10
|
-
ratio: number;
|
|
11
|
-
children: readonly [SplitLayoutNode<L>, SplitLayoutNode<L>];
|
|
12
|
-
}>;
|
|
13
|
-
export type SplitLayoutNode<L extends SplitLayoutLeaf = SplitLayoutLeaf> = L | SplitLayoutBranch<L>;
|
|
14
|
-
export declare const MAX_LAYOUT_LEAVES = 8;
|
|
15
|
-
export declare const MAX_LAYOUT_DEPTH = 8;
|
|
16
|
-
export declare const MIN_SPLIT_RATIO = 0.1;
|
|
17
|
-
export declare const MAX_SPLIT_RATIO = 0.9;
|
|
1
|
+
import type { SplitLayoutLeaf, SplitLayoutBranch, SplitLayoutNode } from './tree';
|
|
2
|
+
export * from './tree';
|
|
18
3
|
export type SplitLayoutState<L extends SplitLayoutLeaf = SplitLayoutLeaf> = Readonly<{
|
|
19
4
|
center: SplitLayoutNode<L>;
|
|
20
5
|
focusedLeafId: string;
|
|
@@ -29,9 +14,6 @@ export type SplitPaneInput<L extends SplitLayoutLeaf = SplitLayoutLeaf> = Readon
|
|
|
29
14
|
leaf: L;
|
|
30
15
|
splitId: string;
|
|
31
16
|
}>;
|
|
32
|
-
export declare function listLeaves<L extends SplitLayoutLeaf>(node: SplitLayoutNode<L>): readonly L[];
|
|
33
|
-
export declare function countLeaves<L extends SplitLayoutLeaf>(node: SplitLayoutNode<L>): number;
|
|
34
|
-
export declare function layoutDepth<L extends SplitLayoutLeaf>(node: SplitLayoutNode<L>): number;
|
|
35
17
|
export declare function createLayoutState<L extends SplitLayoutLeaf>(center: SplitLayoutNode<L>): SplitLayoutState<L>;
|
|
36
18
|
export declare function splitPane<L extends SplitLayoutLeaf>(state: SplitLayoutState<L>, targetLeafId: string, input: SplitPaneInput<L>): SplitLayoutState<L>;
|
|
37
19
|
export declare function closePane<L extends SplitLayoutLeaf>(state: SplitLayoutState<L>, leafId: string, createPlaceholderLeaf: () => L): SplitLayoutState<L>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/split-layout/model.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/split-layout/model.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,5 @@
|
|
|
1
|
+
import { MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, countLeaves, layoutDepth, listLeaves } from "./tree.js";
|
|
1
2
|
//#region src/components/layout/split-layout/model.ts
|
|
2
|
-
var MAX_LAYOUT_LEAVES = 8;
|
|
3
|
-
var MAX_LAYOUT_DEPTH = 8;
|
|
4
|
-
var MIN_SPLIT_RATIO = .1;
|
|
5
|
-
var MAX_SPLIT_RATIO = .9;
|
|
6
|
-
function listLeaves(node) {
|
|
7
|
-
return node.kind === "leaf" ? [node] : [...listLeaves(node.children[0]), ...listLeaves(node.children[1])];
|
|
8
|
-
}
|
|
9
|
-
function countLeaves(node) {
|
|
10
|
-
return node.kind === "leaf" ? 1 : countLeaves(node.children[0]) + countLeaves(node.children[1]);
|
|
11
|
-
}
|
|
12
|
-
function layoutDepth(node) {
|
|
13
|
-
return node.kind === "leaf" ? 1 : 1 + Math.max(layoutDepth(node.children[0]), layoutDepth(node.children[1]));
|
|
14
|
-
}
|
|
15
3
|
function replaceLeaf(node, leafId, replacement) {
|
|
16
4
|
if (node.kind === "leaf") return node.id === leafId ? replacement : node;
|
|
17
5
|
const first = replaceLeaf(node.children[0], leafId, replacement);
|
|
@@ -225,7 +213,7 @@ function normalizeLayout(state) {
|
|
|
225
213
|
};
|
|
226
214
|
const first = visit(node.children[0]);
|
|
227
215
|
const second = visit(node.children[1]);
|
|
228
|
-
const ratio = Number.isFinite(node.ratio) ? Math.min(MAX_SPLIT_RATIO, Math.max(MIN_SPLIT_RATIO, node.ratio)) :
|
|
216
|
+
const ratio = Number.isFinite(node.ratio) ? Math.min(MAX_SPLIT_RATIO, Math.max(MIN_SPLIT_RATIO, node.ratio)) : (MIN_SPLIT_RATIO + MAX_SPLIT_RATIO) / 2;
|
|
229
217
|
const changed = first.changed || second.changed || ratio !== node.ratio;
|
|
230
218
|
return {
|
|
231
219
|
node: changed ? {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","names":[],"sources":["../../../../src/components/layout/split-layout/model.ts"],"sourcesContent":["/*\n * Copyright (c) 2026 Michael Yong\n * Copyright (c) 2026 Muxy\n * SPDX-License-Identifier: MIT\n *\n * Portions of the binary split behavior are substantially translated from:\n * - get-bb/bb apps/app/src/lib/split-layout/ops.ts (MIT), revision\n * 52a9256373d4d36f9b60e9e2a7f333464091a2ac.\n * - muxy-app/muxy Muxy/Models/Workspace/SplitNode.swift (MIT), revision\n * 5c5be8697c57a2fe70cda97fdbaf7c912e2e31b6.\n * Adapted first in Adea packages/dev-view/src/layout/operations.ts at\n * 0322ab09ff5e9775bfddc0bf2d81e1df436dbef7. Extracted here with opaque\n * host-owned leaves and an injected final-pane placeholder; immutable strict\n * binary operations, accepted limits and undoable close are preserved.\n * See NOTICE and docs/research/dev-view-donor-audit.md.\n */\n\n/** A visual identity only. Extend this with host-owned payload; UI never interprets it. */\nexport type SplitLayoutLeaf = Readonly<{ kind: 'leaf'; id: string }>\nexport type SplitLayoutBranch<L extends SplitLayoutLeaf = SplitLayoutLeaf> = Readonly<{\n kind: 'split'\n id: string\n direction: 'row' | 'column'\n ratio: number\n children: readonly [SplitLayoutNode<L>, SplitLayoutNode<L>]\n}>\nexport type SplitLayoutNode<L extends SplitLayoutLeaf = SplitLayoutLeaf> = L | SplitLayoutBranch<L>\n\nexport const MAX_LAYOUT_LEAVES = 8\nexport const MAX_LAYOUT_DEPTH = 8\nexport const MIN_SPLIT_RATIO = 0.1\nexport const MAX_SPLIT_RATIO = 0.9\n\nexport type SplitLayoutState<L extends SplitLayoutLeaf = SplitLayoutLeaf> = Readonly<{\n center: SplitLayoutNode<L>\n focusedLeafId: string\n closed: readonly Readonly<{ center: SplitLayoutNode<L>; leafId: string }>[]\n}>\n\nexport type SplitPaneInput<L extends SplitLayoutLeaf = SplitLayoutLeaf> = Readonly<{\n direction: SplitLayoutBranch<L>['direction']\n placement: 'before' | 'after'\n leaf: L\n splitId: string\n}>\n\nexport function listLeaves<L extends SplitLayoutLeaf>(node: SplitLayoutNode<L>): readonly L[] {\n return node.kind === 'leaf'\n ? [node]\n : [...listLeaves(node.children[0]), ...listLeaves(node.children[1])]\n}\n\nexport function countLeaves<L extends SplitLayoutLeaf>(node: SplitLayoutNode<L>): number {\n return node.kind === 'leaf' ? 1 : countLeaves(node.children[0]) + countLeaves(node.children[1])\n}\n\nexport function layoutDepth<L extends SplitLayoutLeaf>(node: SplitLayoutNode<L>): number {\n return node.kind === 'leaf'\n ? 1\n : 1 + Math.max(layoutDepth(node.children[0]), layoutDepth(node.children[1]))\n}\n\nfunction replaceLeaf<L extends SplitLayoutLeaf>(\n node: SplitLayoutNode<L>,\n leafId: string,\n replacement: SplitLayoutNode<L>\n): SplitLayoutNode<L> {\n if (node.kind === 'leaf') return node.id === leafId ? replacement : node\n const first = replaceLeaf(node.children[0], leafId, replacement)\n const second = replaceLeaf(node.children[1], leafId, replacement)\n return first === node.children[0] && second === node.children[1]\n ? node\n : { ...node, children: [first, second] }\n}\n\nfunction removeLeaf<L extends SplitLayoutLeaf>(\n node: SplitLayoutNode<L>,\n leafId: string\n): SplitLayoutNode<L> | null {\n if (node.kind === 'leaf') return node.id === leafId ? null : node\n const first = removeLeaf(node.children[0], leafId)\n const second = removeLeaf(node.children[1], leafId)\n if (!first) return second\n if (!second) return first\n return first === node.children[0] && second === node.children[1]\n ? node\n : { ...node, children: [first, second] }\n}\n\nfunction containsLeaf<L extends SplitLayoutLeaf>(\n node: SplitLayoutNode<L>,\n leafId: string\n): boolean {\n return node.kind === 'leaf'\n ? node.id === leafId\n : containsLeaf(node.children[0], leafId) || containsLeaf(node.children[1], leafId)\n}\n\nfunction assertUniqueInput<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n leaf: L,\n splitId: string\n) {\n assertLayoutTree(leaf)\n if (typeof splitId !== 'string' || splitId.length === 0)\n throw new Error('invalid_state: split identity must be nonempty')\n const ids = new Set<string>()\n const visit = (node: SplitLayoutNode<L>) => {\n if (ids.has(node.id)) throw new Error('invalid_state: duplicate pane id')\n ids.add(node.id)\n if (node.kind === 'split') node.children.forEach(visit)\n }\n visit(state.center)\n if (ids.has(leaf.id) || ids.has(splitId) || leaf.id === splitId)\n throw new Error('invalid_state: duplicate pane id')\n}\n\n/** Visual-tree validation only; applications still decode and scope persisted preferences. */\nfunction assertLayoutTree<L extends SplitLayoutLeaf>(center: SplitLayoutNode<L>): void {\n const ids = new Set<string>()\n const seen = new WeakSet<object>()\n let leaves = 0\n const visit = (node: SplitLayoutNode<L>, depth: number) => {\n if (depth > MAX_LAYOUT_DEPTH) throw new Error('limit_exceeded: layout depth exceeds eight')\n if (!node || typeof node !== 'object') throw new Error('invalid_state: missing layout node')\n if (seen.has(node)) throw new Error('invalid_state: cyclic or reused layout node')\n seen.add(node)\n if (typeof node.id !== 'string' || node.id.length === 0)\n throw new Error('invalid_state: layout identity must be nonempty')\n if (ids.has(node.id)) throw new Error('invalid_state: duplicate pane id')\n ids.add(node.id)\n if (node.kind === 'leaf') {\n leaves += 1\n if (leaves > MAX_LAYOUT_LEAVES)\n throw new Error('limit_exceeded: layout has more than eight leaves')\n return\n }\n if (\n node.kind !== 'split' ||\n !Array.isArray(node.children) ||\n node.children.length !== 2 ||\n (node.direction !== 'row' && node.direction !== 'column')\n )\n throw new Error('invalid_state: layout must be a strict binary row or column tree')\n visit(node.children[0], depth + 1)\n visit(node.children[1], depth + 1)\n }\n visit(center, 1)\n}\n\nexport function createLayoutState<L extends SplitLayoutLeaf>(\n center: SplitLayoutNode<L>\n): SplitLayoutState<L> {\n assertLayoutTree(center)\n const first = listLeaves(center)[0]\n if (!first) throw new Error('invalid_state: layout requires a leaf')\n return { center, focusedLeafId: first.id, closed: [] }\n}\n\nexport function splitPane<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n targetLeafId: string,\n input: SplitPaneInput<L>\n): SplitLayoutState<L> {\n if (!containsLeaf(state.center, targetLeafId)) return state\n if (countLeaves(state.center) >= MAX_LAYOUT_LEAVES)\n throw new Error('limit_exceeded: center layout has eight leaves')\n assertUniqueInput(state, input.leaf, input.splitId)\n const target = listLeaves(state.center).find((leaf) => leaf.id === targetLeafId)\n if (!target) return state\n const children =\n input.placement === 'before' ? ([input.leaf, target] as const) : ([target, input.leaf] as const)\n const center = replaceLeaf(state.center, targetLeafId, {\n kind: 'split',\n id: input.splitId,\n direction: input.direction,\n ratio: 0.5,\n children,\n })\n if (layoutDepth(center) > MAX_LAYOUT_DEPTH)\n throw new Error('limit_exceeded: center layout depth exceeds eight')\n return { ...state, center, focusedLeafId: input.leaf.id, closed: [] }\n}\n\nexport function closePane<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n leafId: string,\n createPlaceholderLeaf: () => L\n): SplitLayoutState<L> {\n if (!containsLeaf(state.center, leafId)) return state\n const before = state.center\n const readingOrder = listLeaves(before)\n const closedIndex = readingOrder.findIndex((leaf) => leaf.id === leafId)\n const removed = removeLeaf(before, leafId)\n const center: SplitLayoutNode<L> = removed ?? createPlaceholderLeaf()\n if (!removed) {\n if (center.kind !== 'leaf') throw new Error('invalid_state: placeholder must be a leaf')\n assertLayoutTree(center)\n }\n const leaves = listLeaves(center)\n const fallback = leaves[Math.min(closedIndex, leaves.length - 1)] ?? leaves[0]\n if (!fallback) throw new Error('invalid_state: layout requires a leaf')\n return {\n center,\n focusedLeafId: state.focusedLeafId === leafId ? fallback.id : state.focusedLeafId,\n closed: [...state.closed, { center: before, leafId }],\n }\n}\n\nexport function undoClosePane<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>\n): SplitLayoutState<L> {\n const previous = state.closed.at(-1)\n if (!previous) return state\n return {\n center: previous.center,\n focusedLeafId: previous.leafId,\n closed: state.closed.slice(0, -1),\n }\n}\n\nexport function focusPane<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n leafId: string\n): SplitLayoutState<L> {\n return containsLeaf(state.center, leafId) && state.focusedLeafId !== leafId\n ? { ...state, focusedLeafId: leafId }\n : state\n}\n\nexport function swapPanes<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n firstLeafId: string,\n secondLeafId: string\n): SplitLayoutState<L> {\n if (firstLeafId === secondLeafId) return state\n const leaves = listLeaves(state.center)\n const first = leaves.find((leaf) => leaf.id === firstLeafId)\n const second = leaves.find((leaf) => leaf.id === secondLeafId)\n if (!first || !second) return state\n const swap = (node: SplitLayoutNode<L>): SplitLayoutNode<L> => {\n if (node.kind === 'leaf') {\n if (node.id === firstLeafId) return second\n if (node.id === secondLeafId) return first\n return node\n }\n const left = swap(node.children[0])\n const right = swap(node.children[1])\n return left === node.children[0] && right === node.children[1]\n ? node\n : { ...node, children: [left, right] }\n }\n return { ...state, center: swap(state.center), closed: [] }\n}\n\nexport function movePane<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n leafId: string,\n targetLeafId: string,\n placement: 'before' | 'after',\n direction: SplitLayoutBranch<L>['direction'],\n splitId: string\n): SplitLayoutState<L> {\n if (leafId === targetLeafId) return state\n const moving = listLeaves(state.center).find((leaf) => leaf.id === leafId)\n if (!moving || !containsLeaf(state.center, targetLeafId)) return state\n const detached = removeLeaf(state.center, leafId)\n if (!detached) return state\n const moved = splitPane(\n { center: detached, focusedLeafId: state.focusedLeafId, closed: state.closed },\n targetLeafId,\n { direction, placement, leaf: moving, splitId }\n )\n return { ...moved, focusedLeafId: leafId }\n}\n\nexport function resizeSplit<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n splitId: string,\n ratio: number\n): SplitLayoutState<L> {\n if (!Number.isFinite(ratio)) return state\n const nextRatio = Math.min(MAX_SPLIT_RATIO, Math.max(MIN_SPLIT_RATIO, ratio))\n let found = false\n const visit = (node: SplitLayoutNode<L>): SplitLayoutNode<L> => {\n if (node.kind === 'leaf') return node\n if (node.id === splitId) {\n found = true\n return node.ratio === nextRatio ? node : { ...node, ratio: nextRatio }\n }\n const first = visit(node.children[0])\n const second = visit(node.children[1])\n return first === node.children[0] && second === node.children[1]\n ? node\n : { ...node, children: [first, second] }\n }\n const center = visit(state.center)\n return found && center !== state.center ? { ...state, center, closed: [] } : state\n}\n\n/**\n * Pure repair walk ported from bb's size normalization: every split ratio is\n * clamped into the normative range and a non-finite ratio falls back to an\n * even split. Structure, IDs, and focus are untouched.\n */\nexport function normalizeLayout<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>\n): SplitLayoutState<L> {\n const visit = (node: SplitLayoutNode<L>): { node: SplitLayoutNode<L>; changed: boolean } => {\n if (node.kind === 'leaf') return { node, changed: false }\n const first = visit(node.children[0])\n const second = visit(node.children[1])\n const ratio = Number.isFinite(node.ratio)\n ? Math.min(MAX_SPLIT_RATIO, Math.max(MIN_SPLIT_RATIO, node.ratio))\n : (MIN_SPLIT_RATIO + MAX_SPLIT_RATIO) / 2\n const changed = first.changed || second.changed || ratio !== node.ratio\n return {\n node: changed ? { ...node, ratio, children: [first.node, second.node] } : node,\n changed,\n }\n }\n const result = visit(state.center)\n return result.changed ? { ...state, center: result.node } : state\n}\n\n/** The leaf immediately after (`1`) or before (`-1`) the given leaf in reading order. */\nexport function neighborLeaf<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n leafId: string,\n step: 1 | -1\n): L | undefined {\n const leaves = listLeaves(state.center)\n const index = leaves.findIndex((leaf) => leaf.id === leafId)\n if (index < 0) return undefined\n return leaves[index + step]\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"model.js","names":[],"sources":["../../../../src/components/layout/split-layout/model.ts"],"sourcesContent":["/*\n * Copyright (c) 2026 Michael Yong\n * Copyright (c) 2026 Muxy\n * SPDX-License-Identifier: MIT\n *\n * Portions of the binary split behavior are substantially translated from:\n * - get-bb/bb apps/app/src/lib/split-layout/ops.ts (MIT), revision\n * 52a9256373d4d36f9b60e9e2a7f333464091a2ac.\n * - muxy-app/muxy Muxy/Models/Workspace/SplitNode.swift (MIT), revision\n * 5c5be8697c57a2fe70cda97fdbaf7c912e2e31b6.\n * Adapted first in Adea packages/dev-view/src/layout/operations.ts at\n * 0322ab09ff5e9775bfddc0bf2d81e1df436dbef7. Extracted here with opaque\n * host-owned leaves and an injected final-pane placeholder; immutable strict\n * binary operations, accepted limits and undoable close are preserved.\n * See NOTICE and docs/research/dev-view-donor-audit.md.\n */\n\nimport {\n MAX_LAYOUT_LEAVES,\n MAX_LAYOUT_DEPTH,\n MIN_SPLIT_RATIO,\n MAX_SPLIT_RATIO,\n listLeaves,\n countLeaves,\n layoutDepth,\n} from './tree'\nimport type { SplitLayoutLeaf, SplitLayoutBranch, SplitLayoutNode } from './tree'\n\nexport * from './tree'\n\nexport type SplitLayoutState<L extends SplitLayoutLeaf = SplitLayoutLeaf> = Readonly<{\n center: SplitLayoutNode<L>\n focusedLeafId: string\n closed: readonly Readonly<{ center: SplitLayoutNode<L>; leafId: string }>[]\n}>\n\nexport type SplitPaneInput<L extends SplitLayoutLeaf = SplitLayoutLeaf> = Readonly<{\n direction: SplitLayoutBranch<L>['direction']\n placement: 'before' | 'after'\n leaf: L\n splitId: string\n}>\n\nfunction replaceLeaf<L extends SplitLayoutLeaf>(\n node: SplitLayoutNode<L>,\n leafId: string,\n replacement: SplitLayoutNode<L>\n): SplitLayoutNode<L> {\n if (node.kind === 'leaf') return node.id === leafId ? replacement : node\n const first = replaceLeaf(node.children[0], leafId, replacement)\n const second = replaceLeaf(node.children[1], leafId, replacement)\n return first === node.children[0] && second === node.children[1]\n ? node\n : { ...node, children: [first, second] }\n}\n\nfunction removeLeaf<L extends SplitLayoutLeaf>(\n node: SplitLayoutNode<L>,\n leafId: string\n): SplitLayoutNode<L> | null {\n if (node.kind === 'leaf') return node.id === leafId ? null : node\n const first = removeLeaf(node.children[0], leafId)\n const second = removeLeaf(node.children[1], leafId)\n if (!first) return second\n if (!second) return first\n return first === node.children[0] && second === node.children[1]\n ? node\n : { ...node, children: [first, second] }\n}\n\nfunction containsLeaf<L extends SplitLayoutLeaf>(\n node: SplitLayoutNode<L>,\n leafId: string\n): boolean {\n return node.kind === 'leaf'\n ? node.id === leafId\n : containsLeaf(node.children[0], leafId) || containsLeaf(node.children[1], leafId)\n}\n\nfunction assertUniqueInput<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n leaf: L,\n splitId: string\n) {\n assertLayoutTree(leaf)\n if (typeof splitId !== 'string' || splitId.length === 0)\n throw new Error('invalid_state: split identity must be nonempty')\n const ids = new Set<string>()\n const visit = (node: SplitLayoutNode<L>) => {\n if (ids.has(node.id)) throw new Error('invalid_state: duplicate pane id')\n ids.add(node.id)\n if (node.kind === 'split') node.children.forEach(visit)\n }\n visit(state.center)\n if (ids.has(leaf.id) || ids.has(splitId) || leaf.id === splitId)\n throw new Error('invalid_state: duplicate pane id')\n}\n\n/** Visual-tree validation only; applications still decode and scope persisted preferences. */\nfunction assertLayoutTree<L extends SplitLayoutLeaf>(center: SplitLayoutNode<L>): void {\n const ids = new Set<string>()\n const seen = new WeakSet<object>()\n let leaves = 0\n const visit = (node: SplitLayoutNode<L>, depth: number) => {\n if (depth > MAX_LAYOUT_DEPTH) throw new Error('limit_exceeded: layout depth exceeds eight')\n if (!node || typeof node !== 'object') throw new Error('invalid_state: missing layout node')\n if (seen.has(node)) throw new Error('invalid_state: cyclic or reused layout node')\n seen.add(node)\n if (typeof node.id !== 'string' || node.id.length === 0)\n throw new Error('invalid_state: layout identity must be nonempty')\n if (ids.has(node.id)) throw new Error('invalid_state: duplicate pane id')\n ids.add(node.id)\n if (node.kind === 'leaf') {\n leaves += 1\n if (leaves > MAX_LAYOUT_LEAVES)\n throw new Error('limit_exceeded: layout has more than eight leaves')\n return\n }\n if (\n node.kind !== 'split' ||\n !Array.isArray(node.children) ||\n node.children.length !== 2 ||\n (node.direction !== 'row' && node.direction !== 'column')\n )\n throw new Error('invalid_state: layout must be a strict binary row or column tree')\n visit(node.children[0], depth + 1)\n visit(node.children[1], depth + 1)\n }\n visit(center, 1)\n}\n\nexport function createLayoutState<L extends SplitLayoutLeaf>(\n center: SplitLayoutNode<L>\n): SplitLayoutState<L> {\n assertLayoutTree(center)\n const first = listLeaves(center)[0]\n if (!first) throw new Error('invalid_state: layout requires a leaf')\n return { center, focusedLeafId: first.id, closed: [] }\n}\n\nexport function splitPane<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n targetLeafId: string,\n input: SplitPaneInput<L>\n): SplitLayoutState<L> {\n if (!containsLeaf(state.center, targetLeafId)) return state\n if (countLeaves(state.center) >= MAX_LAYOUT_LEAVES)\n throw new Error('limit_exceeded: center layout has eight leaves')\n assertUniqueInput(state, input.leaf, input.splitId)\n const target = listLeaves(state.center).find((leaf) => leaf.id === targetLeafId)\n if (!target) return state\n const children =\n input.placement === 'before' ? ([input.leaf, target] as const) : ([target, input.leaf] as const)\n const center = replaceLeaf(state.center, targetLeafId, {\n kind: 'split',\n id: input.splitId,\n direction: input.direction,\n ratio: 0.5,\n children,\n })\n if (layoutDepth(center) > MAX_LAYOUT_DEPTH)\n throw new Error('limit_exceeded: center layout depth exceeds eight')\n return { ...state, center, focusedLeafId: input.leaf.id, closed: [] }\n}\n\nexport function closePane<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n leafId: string,\n createPlaceholderLeaf: () => L\n): SplitLayoutState<L> {\n if (!containsLeaf(state.center, leafId)) return state\n const before = state.center\n const readingOrder = listLeaves(before)\n const closedIndex = readingOrder.findIndex((leaf) => leaf.id === leafId)\n const removed = removeLeaf(before, leafId)\n const center: SplitLayoutNode<L> = removed ?? createPlaceholderLeaf()\n if (!removed) {\n if (center.kind !== 'leaf') throw new Error('invalid_state: placeholder must be a leaf')\n assertLayoutTree(center)\n }\n const leaves = listLeaves(center)\n const fallback = leaves[Math.min(closedIndex, leaves.length - 1)] ?? leaves[0]\n if (!fallback) throw new Error('invalid_state: layout requires a leaf')\n return {\n center,\n focusedLeafId: state.focusedLeafId === leafId ? fallback.id : state.focusedLeafId,\n closed: [...state.closed, { center: before, leafId }],\n }\n}\n\nexport function undoClosePane<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>\n): SplitLayoutState<L> {\n const previous = state.closed.at(-1)\n if (!previous) return state\n return {\n center: previous.center,\n focusedLeafId: previous.leafId,\n closed: state.closed.slice(0, -1),\n }\n}\n\nexport function focusPane<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n leafId: string\n): SplitLayoutState<L> {\n return containsLeaf(state.center, leafId) && state.focusedLeafId !== leafId\n ? { ...state, focusedLeafId: leafId }\n : state\n}\n\nexport function swapPanes<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n firstLeafId: string,\n secondLeafId: string\n): SplitLayoutState<L> {\n if (firstLeafId === secondLeafId) return state\n const leaves = listLeaves(state.center)\n const first = leaves.find((leaf) => leaf.id === firstLeafId)\n const second = leaves.find((leaf) => leaf.id === secondLeafId)\n if (!first || !second) return state\n const swap = (node: SplitLayoutNode<L>): SplitLayoutNode<L> => {\n if (node.kind === 'leaf') {\n if (node.id === firstLeafId) return second\n if (node.id === secondLeafId) return first\n return node\n }\n const left = swap(node.children[0])\n const right = swap(node.children[1])\n return left === node.children[0] && right === node.children[1]\n ? node\n : { ...node, children: [left, right] }\n }\n return { ...state, center: swap(state.center), closed: [] }\n}\n\nexport function movePane<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n leafId: string,\n targetLeafId: string,\n placement: 'before' | 'after',\n direction: SplitLayoutBranch<L>['direction'],\n splitId: string\n): SplitLayoutState<L> {\n if (leafId === targetLeafId) return state\n const moving = listLeaves(state.center).find((leaf) => leaf.id === leafId)\n if (!moving || !containsLeaf(state.center, targetLeafId)) return state\n const detached = removeLeaf(state.center, leafId)\n if (!detached) return state\n const moved = splitPane(\n { center: detached, focusedLeafId: state.focusedLeafId, closed: state.closed },\n targetLeafId,\n { direction, placement, leaf: moving, splitId }\n )\n return { ...moved, focusedLeafId: leafId }\n}\n\nexport function resizeSplit<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n splitId: string,\n ratio: number\n): SplitLayoutState<L> {\n if (!Number.isFinite(ratio)) return state\n const nextRatio = Math.min(MAX_SPLIT_RATIO, Math.max(MIN_SPLIT_RATIO, ratio))\n let found = false\n const visit = (node: SplitLayoutNode<L>): SplitLayoutNode<L> => {\n if (node.kind === 'leaf') return node\n if (node.id === splitId) {\n found = true\n return node.ratio === nextRatio ? node : { ...node, ratio: nextRatio }\n }\n const first = visit(node.children[0])\n const second = visit(node.children[1])\n return first === node.children[0] && second === node.children[1]\n ? node\n : { ...node, children: [first, second] }\n }\n const center = visit(state.center)\n return found && center !== state.center ? { ...state, center, closed: [] } : state\n}\n\n/**\n * Pure repair walk ported from bb's size normalization: every split ratio is\n * clamped into the normative range and a non-finite ratio falls back to an\n * even split. Structure, IDs, and focus are untouched.\n */\nexport function normalizeLayout<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>\n): SplitLayoutState<L> {\n const visit = (node: SplitLayoutNode<L>): { node: SplitLayoutNode<L>; changed: boolean } => {\n if (node.kind === 'leaf') return { node, changed: false }\n const first = visit(node.children[0])\n const second = visit(node.children[1])\n const ratio = Number.isFinite(node.ratio)\n ? Math.min(MAX_SPLIT_RATIO, Math.max(MIN_SPLIT_RATIO, node.ratio))\n : (MIN_SPLIT_RATIO + MAX_SPLIT_RATIO) / 2\n const changed = first.changed || second.changed || ratio !== node.ratio\n return {\n node: changed ? { ...node, ratio, children: [first.node, second.node] } : node,\n changed,\n }\n }\n const result = visit(state.center)\n return result.changed ? { ...state, center: result.node } : state\n}\n\n/** The leaf immediately after (`1`) or before (`-1`) the given leaf in reading order. */\nexport function neighborLeaf<L extends SplitLayoutLeaf>(\n state: SplitLayoutState<L>,\n leafId: string,\n step: 1 | -1\n): L | undefined {\n const leaves = listLeaves(state.center)\n const index = leaves.findIndex((leaf) => leaf.id === leafId)\n if (index < 0) return undefined\n return leaves[index + step]\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cn } from "../../../lib/utils.js";
|
|
2
2
|
import { Button } from "../../ui/button/button.js";
|
|
3
|
-
import { MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, listLeaves } from "./
|
|
3
|
+
import { MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, listLeaves } from "./tree.js";
|
|
4
4
|
import { computeLayoutFrames } from "./geometry.js";
|
|
5
5
|
import { paneDropIntent } from "./drop.js";
|
|
6
6
|
import { className, createComponent, delegateEvents, effect, insert, memo, setAttribute, style, template, use } from "solid-js/web";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** A visual identity only. Extend this with host-owned payload; UI never interprets it. */
|
|
2
|
+
export type SplitLayoutLeaf = Readonly<{
|
|
3
|
+
kind: 'leaf';
|
|
4
|
+
id: string;
|
|
5
|
+
}>;
|
|
6
|
+
export type SplitLayoutBranch<L extends SplitLayoutLeaf = SplitLayoutLeaf> = Readonly<{
|
|
7
|
+
kind: 'split';
|
|
8
|
+
id: string;
|
|
9
|
+
direction: 'row' | 'column';
|
|
10
|
+
ratio: number;
|
|
11
|
+
children: readonly [SplitLayoutNode<L>, SplitLayoutNode<L>];
|
|
12
|
+
}>;
|
|
13
|
+
export type SplitLayoutNode<L extends SplitLayoutLeaf = SplitLayoutLeaf> = L | SplitLayoutBranch<L>;
|
|
14
|
+
export declare const MAX_LAYOUT_LEAVES = 8;
|
|
15
|
+
export declare const MAX_LAYOUT_DEPTH = 8;
|
|
16
|
+
export declare const MIN_SPLIT_RATIO = 0.1;
|
|
17
|
+
export declare const MAX_SPLIT_RATIO = 0.9;
|
|
18
|
+
export declare function listLeaves<L extends SplitLayoutLeaf>(node: SplitLayoutNode<L>): readonly L[];
|
|
19
|
+
export declare function countLeaves<L extends SplitLayoutLeaf>(node: SplitLayoutNode<L>): number;
|
|
20
|
+
export declare function layoutDepth<L extends SplitLayoutLeaf>(node: SplitLayoutNode<L>): number;
|
|
21
|
+
//# sourceMappingURL=tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/split-layout/tree.ts"],"names":[],"mappings":"AAoBA,2FAA2F;AAC3F,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AACpE,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe,IAAI,QAAQ,CAAC;IACpF,IAAI,EAAE,OAAO,CAAA;IACb,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,KAAK,GAAG,QAAQ,CAAA;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAA;CAC5D,CAAC,CAAA;AACF,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe,IAAI,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAA;AAEnG,eAAO,MAAM,iBAAiB,IAAI,CAAA;AAClC,eAAO,MAAM,gBAAgB,IAAI,CAAA;AACjC,eAAO,MAAM,eAAe,MAAM,CAAA;AAClC,eAAO,MAAM,eAAe,MAAM,CAAA;AAElC,wBAAgB,UAAU,CAAC,CAAC,SAAS,eAAe,EAAE,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,CAI5F;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,eAAe,EAAE,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,MAAM,CAEvF;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,eAAe,EAAE,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,MAAM,CAIvF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/components/layout/split-layout/tree.ts
|
|
2
|
+
var MAX_LAYOUT_LEAVES = 8;
|
|
3
|
+
var MAX_LAYOUT_DEPTH = 8;
|
|
4
|
+
var MIN_SPLIT_RATIO = .1;
|
|
5
|
+
var MAX_SPLIT_RATIO = .9;
|
|
6
|
+
function listLeaves(node) {
|
|
7
|
+
return node.kind === "leaf" ? [node] : [...listLeaves(node.children[0]), ...listLeaves(node.children[1])];
|
|
8
|
+
}
|
|
9
|
+
function countLeaves(node) {
|
|
10
|
+
return node.kind === "leaf" ? 1 : countLeaves(node.children[0]) + countLeaves(node.children[1]);
|
|
11
|
+
}
|
|
12
|
+
function layoutDepth(node) {
|
|
13
|
+
return node.kind === "leaf" ? 1 : 1 + Math.max(layoutDepth(node.children[0]), layoutDepth(node.children[1]));
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, countLeaves, layoutDepth, listLeaves };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.js","names":[],"sources":["../../../../src/components/layout/split-layout/tree.ts"],"sourcesContent":["/*\n * Copyright (c) 2026 Michael Yong\n * Copyright (c) 2026 Muxy\n * SPDX-License-Identifier: MIT\n *\n * Portions of the binary split behavior are substantially translated from:\n * - get-bb/bb apps/app/src/lib/split-layout/ops.ts (MIT), revision\n * 52a9256373d4d36f9b60e9e2a7f333464091a2ac.\n * - muxy-app/muxy Muxy/Models/Workspace/SplitNode.swift (MIT), revision\n * 5c5be8697c57a2fe70cda97fdbaf7c912e2e31b6.\n * Adapted first in Adea packages/dev-view/src/layout/operations.ts at\n * 0322ab09ff5e9775bfddc0bf2d81e1df436dbef7. Extracted here with opaque\n * host-owned leaves and an injected final-pane placeholder; immutable strict\n * binary operations, accepted limits and undoable close are preserved.\n * See NOTICE and docs/research/dev-view-donor-audit.md.\n */\n\n// Read-only tree shape, limits, and traversal form a small import boundary.\n// Persistence decoders can use these without loading pane-editing operations.\n\n/** A visual identity only. Extend this with host-owned payload; UI never interprets it. */\nexport type SplitLayoutLeaf = Readonly<{ kind: 'leaf'; id: string }>\nexport type SplitLayoutBranch<L extends SplitLayoutLeaf = SplitLayoutLeaf> = Readonly<{\n kind: 'split'\n id: string\n direction: 'row' | 'column'\n ratio: number\n children: readonly [SplitLayoutNode<L>, SplitLayoutNode<L>]\n}>\nexport type SplitLayoutNode<L extends SplitLayoutLeaf = SplitLayoutLeaf> = L | SplitLayoutBranch<L>\n\nexport const MAX_LAYOUT_LEAVES = 8\nexport const MAX_LAYOUT_DEPTH = 8\nexport const MIN_SPLIT_RATIO = 0.1\nexport const MAX_SPLIT_RATIO = 0.9\n\nexport function listLeaves<L extends SplitLayoutLeaf>(node: SplitLayoutNode<L>): readonly L[] {\n return node.kind === 'leaf'\n ? [node]\n : [...listLeaves(node.children[0]), ...listLeaves(node.children[1])]\n}\n\nexport function countLeaves<L extends SplitLayoutLeaf>(node: SplitLayoutNode<L>): number {\n return node.kind === 'leaf' ? 1 : countLeaves(node.children[0]) + countLeaves(node.children[1])\n}\n\nexport function layoutDepth<L extends SplitLayoutLeaf>(node: SplitLayoutNode<L>): number {\n return node.kind === 'leaf'\n ? 1\n : 1 + Math.max(layoutDepth(node.children[0]), layoutDepth(node.children[1]))\n}\n"],"mappings":";AA+BA,IAAa,oBAAoB;AACjC,IAAa,mBAAmB;AAChC,IAAa,kBAAkB;AAC/B,IAAa,kBAAkB;AAE/B,SAAgB,WAAsC,MAAwC;CAC5F,OAAO,KAAK,SAAS,SACjB,CAAC,IAAI,IACL,CAAC,GAAG,WAAW,KAAK,SAAS,EAAE,GAAG,GAAG,WAAW,KAAK,SAAS,EAAE,CAAC;AACvE;AAEA,SAAgB,YAAuC,MAAkC;CACvF,OAAO,KAAK,SAAS,SAAS,IAAI,YAAY,KAAK,SAAS,EAAE,IAAI,YAAY,KAAK,SAAS,EAAE;AAChG;AAEA,SAAgB,YAAuC,MAAkC;CACvF,OAAO,KAAK,SAAS,SACjB,IACA,IAAI,KAAK,IAAI,YAAY,KAAK,SAAS,EAAE,GAAG,YAAY,KAAK,SAAS,EAAE,CAAC;AAC/E"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { Kbd, KbdGroup } from './kbd';
|
|
1
|
+
export { Kbd, KbdChord, KbdGroup, kbdChordKeys, kbdGroupVariants, kbdVariants, type KbdChordProps, type KbdSize, } from './kbd';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/kbd/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/kbd/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EACH,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,OAAO,GACb,MAAM,OAAO,CAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Kbd, KbdGroup } from "./kbd.js";
|
|
2
|
-
export { Kbd, KbdGroup };
|
|
1
|
+
import { Kbd, KbdChord, KbdGroup, kbdChordKeys, kbdGroupVariants, kbdVariants } from "./kbd.js";
|
|
2
|
+
export { Kbd, KbdChord, KbdGroup, kbdChordKeys, kbdGroupVariants, kbdVariants };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ComponentProps } from 'solid-js';
|
|
2
|
+
import { type VariantProps } from '#lib/variants';
|
|
2
3
|
/**
|
|
3
4
|
* Kbd.
|
|
4
5
|
*
|
|
@@ -6,9 +7,46 @@ import type { ComponentProps } from 'solid-js';
|
|
|
6
7
|
* `<kbd>` so the semantics survive copy-paste, and the mono face is what makes
|
|
7
8
|
* a shortcut visually distinct from the sentence around it.
|
|
8
9
|
*
|
|
10
|
+
* `size="compact"` exists for the dense rows a default cap would outweigh — a
|
|
11
|
+
* rail search row, a sidebar shortcut hint. It drops a height rung, and it
|
|
12
|
+
* lightens the fill and weight with it because at that size a solid muted cap
|
|
13
|
+
* reads heavier than the row text it sits in. The default rendering is every
|
|
14
|
+
* cap that is not inside such a row, and it is untouched by the rung.
|
|
15
|
+
*
|
|
9
16
|
* `KbdGroup` exists because a shortcut is a sequence: typing `⌘` then `K`
|
|
10
17
|
* needs a gap between them that is a layout concern, not punctuation.
|
|
11
18
|
*/
|
|
12
|
-
export declare
|
|
13
|
-
|
|
19
|
+
export declare const kbdVariants: (props?: ({
|
|
20
|
+
size?: "default" | "compact" | null | undefined;
|
|
21
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
22
|
+
export type KbdSize = NonNullable<VariantProps<typeof kbdVariants>['size']>;
|
|
23
|
+
export declare function Kbd(props: ComponentProps<'kbd'> & {
|
|
24
|
+
size?: KbdSize;
|
|
25
|
+
}): import("solid-js").JSX.Element;
|
|
26
|
+
export declare const kbdGroupVariants: (props?: ({
|
|
27
|
+
size?: "default" | "compact" | null | undefined;
|
|
28
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
29
|
+
export declare function KbdGroup(props: ComponentProps<'span'> & {
|
|
30
|
+
size?: KbdSize;
|
|
31
|
+
}): import("solid-js").JSX.Element;
|
|
32
|
+
/**
|
|
33
|
+
* Split a written chord into one entry per key cap. Every character is a key:
|
|
34
|
+
* `⌘K` renders as `⌘` + `K`, and a longer chord like `⇧⌘P` stays three caps
|
|
35
|
+
* wide, which matches how the system draws chords in menus.
|
|
36
|
+
*/
|
|
37
|
+
export declare function kbdChordKeys(keys: string): string[];
|
|
38
|
+
export type KbdChordProps = Omit<ComponentProps<'span'>, 'children'> & {
|
|
39
|
+
/** The chord as it is drawn, e.g. `"⌘K"` or `"⇧⌘P"`. One cap per character. */
|
|
40
|
+
keys: string;
|
|
41
|
+
size?: KbdSize;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* KbdChord.
|
|
45
|
+
*
|
|
46
|
+
* A written chord drawn as caps, one per character. Decoration only: the
|
|
47
|
+
* composition renders `aria-hidden`, so the accessible name and the parseable
|
|
48
|
+
* `aria-keyshortcuts` stay on the control the chord belongs to. That is why
|
|
49
|
+
* there is no children — the chord says what was drawn, nothing more.
|
|
50
|
+
*/
|
|
51
|
+
export declare function KbdChord(props: KbdChordProps): import("solid-js").JSX.Element;
|
|
14
52
|
//# sourceMappingURL=kbd.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kbd.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/kbd/kbd.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"kbd.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/kbd/kbd.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAE9C,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAGtD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,WAAW;;8EAavB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AAE3E,wBAAgB,GAAG,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,kCAMpE;AAED,eAAO,MAAM,gBAAgB;;8EAW3B,CAAA;AAEF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,kCAU1E;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEnD;AAED,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,GAAG;IACrE,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,kCAQ5C"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cn } from "../../../lib/utils.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { cva } from "../../../lib/variants.js";
|
|
3
|
+
import { createComponent, mergeProps, spread, template } from "solid-js/web";
|
|
4
|
+
import { For, splitProps } from "solid-js";
|
|
4
5
|
//#region src/components/ui/kbd/kbd.tsx
|
|
5
6
|
var _tmpl$ = /*#__PURE__*/ template(`<kbd data-slot=kbd>`);
|
|
6
7
|
var _tmpl$2 = /*#__PURE__*/ template(`<span data-slot=kbd-group>`);
|
|
@@ -11,30 +12,96 @@ var _tmpl$2 = /*#__PURE__*/ template(`<span data-slot=kbd-group>`);
|
|
|
11
12
|
* `<kbd>` so the semantics survive copy-paste, and the mono face is what makes
|
|
12
13
|
* a shortcut visually distinct from the sentence around it.
|
|
13
14
|
*
|
|
15
|
+
* `size="compact"` exists for the dense rows a default cap would outweigh — a
|
|
16
|
+
* rail search row, a sidebar shortcut hint. It drops a height rung, and it
|
|
17
|
+
* lightens the fill and weight with it because at that size a solid muted cap
|
|
18
|
+
* reads heavier than the row text it sits in. The default rendering is every
|
|
19
|
+
* cap that is not inside such a row, and it is untouched by the rung.
|
|
20
|
+
*
|
|
14
21
|
* `KbdGroup` exists because a shortcut is a sequence: typing `⌘` then `K`
|
|
15
22
|
* needs a gap between them that is a layout concern, not punctuation.
|
|
16
23
|
*/
|
|
24
|
+
var kbdVariants = cva("bg-muted text-muted-foreground pointer-events-none inline-flex h-5 min-w-5 items-center justify-center gap-1 rounded-sm border border-border px-1 font-mono text-2xs font-medium select-none", {
|
|
25
|
+
variants: { size: {
|
|
26
|
+
default: "",
|
|
27
|
+
compact: "h-4 min-w-4 bg-muted/40 px-0.5 font-normal leading-none"
|
|
28
|
+
} },
|
|
29
|
+
defaultVariants: { size: "default" }
|
|
30
|
+
});
|
|
17
31
|
function Kbd(props) {
|
|
18
|
-
const [local, rest] = splitProps(props, ["class"]);
|
|
32
|
+
const [local, rest] = splitProps(props, ["size", "class"]);
|
|
19
33
|
return (() => {
|
|
20
34
|
var _el$ = _tmpl$();
|
|
21
35
|
spread(_el$, mergeProps({ get ["class"]() {
|
|
22
|
-
return cn(
|
|
36
|
+
return cn(kbdVariants({ size: local.size }), local.class);
|
|
23
37
|
} }, rest), false, false);
|
|
24
38
|
return _el$;
|
|
25
39
|
})();
|
|
26
40
|
}
|
|
41
|
+
var kbdGroupVariants = cva("inline-flex items-center gap-1", {
|
|
42
|
+
variants: { size: {
|
|
43
|
+
default: "",
|
|
44
|
+
/** The gap is what separates caps, so it tightens with them. */
|
|
45
|
+
compact: "gap-0.5"
|
|
46
|
+
} },
|
|
47
|
+
defaultVariants: { size: "default" }
|
|
48
|
+
});
|
|
27
49
|
function KbdGroup(props) {
|
|
28
|
-
const [local, rest] = splitProps(props, ["class"]);
|
|
50
|
+
const [local, rest] = splitProps(props, ["size", "class"]);
|
|
29
51
|
return (() => {
|
|
30
52
|
var _el$2 = _tmpl$2();
|
|
31
53
|
spread(_el$2, mergeProps({ get ["class"]() {
|
|
32
|
-
return cn(
|
|
54
|
+
return cn(kbdGroupVariants({ size: local.size }), local.class);
|
|
33
55
|
} }, rest), false, false);
|
|
34
56
|
return _el$2;
|
|
35
57
|
})();
|
|
36
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Split a written chord into one entry per key cap. Every character is a key:
|
|
61
|
+
* `⌘K` renders as `⌘` + `K`, and a longer chord like `⇧⌘P` stays three caps
|
|
62
|
+
* wide, which matches how the system draws chords in menus.
|
|
63
|
+
*/
|
|
64
|
+
function kbdChordKeys(keys) {
|
|
65
|
+
return [...keys];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* KbdChord.
|
|
69
|
+
*
|
|
70
|
+
* A written chord drawn as caps, one per character. Decoration only: the
|
|
71
|
+
* composition renders `aria-hidden`, so the accessible name and the parseable
|
|
72
|
+
* `aria-keyshortcuts` stay on the control the chord belongs to. That is why
|
|
73
|
+
* there is no children — the chord says what was drawn, nothing more.
|
|
74
|
+
*/
|
|
75
|
+
function KbdChord(props) {
|
|
76
|
+
const [local, rest] = splitProps(props, [
|
|
77
|
+
"keys",
|
|
78
|
+
"size",
|
|
79
|
+
"class"
|
|
80
|
+
]);
|
|
81
|
+
return createComponent(KbdGroup, mergeProps(rest, {
|
|
82
|
+
get size() {
|
|
83
|
+
return local.size;
|
|
84
|
+
},
|
|
85
|
+
get ["class"]() {
|
|
86
|
+
return local.class;
|
|
87
|
+
},
|
|
88
|
+
"aria-hidden": "true",
|
|
89
|
+
get children() {
|
|
90
|
+
return createComponent(For, {
|
|
91
|
+
get each() {
|
|
92
|
+
return kbdChordKeys(local.keys);
|
|
93
|
+
},
|
|
94
|
+
children: (key) => createComponent(Kbd, {
|
|
95
|
+
get size() {
|
|
96
|
+
return local.size;
|
|
97
|
+
},
|
|
98
|
+
children: key
|
|
99
|
+
})
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
37
104
|
//#endregion
|
|
38
|
-
export { Kbd, KbdGroup };
|
|
105
|
+
export { Kbd, KbdChord, KbdGroup, kbdChordKeys, kbdGroupVariants, kbdVariants };
|
|
39
106
|
|
|
40
107
|
//# sourceMappingURL=kbd.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kbd.js","names":["ComponentProps","splitProps","cn","Kbd","props","local","rest","_el$","_tmpl$","_$spread","_$mergeProps","class","KbdGroup","_el$2","_tmpl$2","_$mergeProps"],"sources":["../../../../src/components/ui/kbd/kbd.tsx"],"sourcesContent":["import type { ComponentProps } from 'solid-js'\nimport { splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\n\n/**\n * Kbd.\n *\n * A keyboard key, in the order the user presses them. The element is a real\n * `<kbd>` so the semantics survive copy-paste, and the mono face is what makes\n * a shortcut visually distinct from the sentence around it.\n *\n * `KbdGroup` exists because a shortcut is a sequence: typing `⌘` then `K`\n * needs a gap between them that is a layout concern, not punctuation.\n */\nexport function Kbd(props: ComponentProps<'kbd'>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <kbd
|
|
1
|
+
{"version":3,"file":"kbd.js","names":["ComponentProps","For","splitProps","cva","VariantProps","cn","kbdVariants","variants","size","default","compact","defaultVariants","KbdSize","NonNullable","Kbd","props","local","rest","_el$","_tmpl$","_$spread","_$mergeProps","class","kbdGroupVariants","KbdGroup","_el$2","_tmpl$2","kbdChordKeys","keys","KbdChordProps","Omit","KbdChord","_$createComponent","children","each","key","_$mergeProps","_$createComponent"],"sources":["../../../../src/components/ui/kbd/kbd.tsx"],"sourcesContent":["import type { ComponentProps } from 'solid-js'\nimport { For, splitProps } from 'solid-js'\nimport { cva, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\n\n/**\n * Kbd.\n *\n * A keyboard key, in the order the user presses them. The element is a real\n * `<kbd>` so the semantics survive copy-paste, and the mono face is what makes\n * a shortcut visually distinct from the sentence around it.\n *\n * `size=\"compact\"` exists for the dense rows a default cap would outweigh — a\n * rail search row, a sidebar shortcut hint. It drops a height rung, and it\n * lightens the fill and weight with it because at that size a solid muted cap\n * reads heavier than the row text it sits in. The default rendering is every\n * cap that is not inside such a row, and it is untouched by the rung.\n *\n * `KbdGroup` exists because a shortcut is a sequence: typing `⌘` then `K`\n * needs a gap between them that is a layout concern, not punctuation.\n */\nexport const kbdVariants = cva(\n 'bg-muted text-muted-foreground pointer-events-none inline-flex h-5 min-w-5 items-center justify-center gap-1 rounded-sm border border-border px-1 font-mono text-2xs font-medium select-none',\n {\n variants: {\n size: {\n default: '',\n compact: 'h-4 min-w-4 bg-muted/40 px-0.5 font-normal leading-none',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n }\n)\n\nexport type KbdSize = NonNullable<VariantProps<typeof kbdVariants>['size']>\n\nexport function Kbd(props: ComponentProps<'kbd'> & { size?: KbdSize }) {\n const [local, rest] = splitProps(props, ['size', 'class'])\n\n return (\n <kbd data-slot=\"kbd\" class={cn(kbdVariants({ size: local.size }), local.class)} {...rest} />\n )\n}\n\nexport const kbdGroupVariants = cva('inline-flex items-center gap-1', {\n variants: {\n size: {\n default: '',\n /** The gap is what separates caps, so it tightens with them. */\n compact: 'gap-0.5',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n})\n\nexport function KbdGroup(props: ComponentProps<'span'> & { size?: KbdSize }) {\n const [local, rest] = splitProps(props, ['size', 'class'])\n\n return (\n <span\n data-slot=\"kbd-group\"\n class={cn(kbdGroupVariants({ size: local.size }), local.class)}\n {...rest}\n />\n )\n}\n\n/**\n * Split a written chord into one entry per key cap. Every character is a key:\n * `⌘K` renders as `⌘` + `K`, and a longer chord like `⇧⌘P` stays three caps\n * wide, which matches how the system draws chords in menus.\n */\nexport function kbdChordKeys(keys: string): string[] {\n return [...keys]\n}\n\nexport type KbdChordProps = Omit<ComponentProps<'span'>, 'children'> & {\n /** The chord as it is drawn, e.g. `\"⌘K\"` or `\"⇧⌘P\"`. One cap per character. */\n keys: string\n size?: KbdSize\n}\n\n/**\n * KbdChord.\n *\n * A written chord drawn as caps, one per character. Decoration only: the\n * composition renders `aria-hidden`, so the accessible name and the parseable\n * `aria-keyshortcuts` stay on the control the chord belongs to. That is why\n * there is no children — the chord says what was drawn, nothing more.\n */\nexport function KbdChord(props: KbdChordProps) {\n const [local, rest] = splitProps(props, ['keys', 'size', 'class'])\n\n return (\n <KbdGroup {...rest} size={local.size} class={local.class} aria-hidden=\"true\">\n <For each={kbdChordKeys(local.keys)}>{(key) => <Kbd size={local.size}>{key}</Kbd>}</For>\n </KbdGroup>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAqBA,IAAaM,cAAcH,IACzB,gMACA;CACEI,UAAU,EACRC,MAAM;EACJC,SAAS;EACTC,SAAS;CACX,EACF;CACAC,iBAAiB,EACfH,MAAM,UACR;AACF,CACF;AAIA,SAAgBM,IAAIC,OAAmD;CACrE,MAAM,CAACC,OAAOC,QAAQf,WAAWa,OAAO,CAAC,QAAQ,OAAO,CAAC;CAEzD,cAAA;EAAA,IAAAG,OAAAC,OAAA;EAAAC,OAAAF,MAAAG,WAAA,EAAA,KAAA,WAAA;GAAA,OAC8BhB,GAAGC,YAAY,EAAEE,MAAMQ,MAAMR,KAAK,CAAC,GAAGQ,MAAMM,KAAK;EAAC,EAAA,GAAML,IAAI,GAAA,OAAA,KAAA;EAAA,OAAAC;CAAA,EAAA,CAAA;AAE5F;AAEA,IAAaK,mBAAmBpB,IAAI,kCAAkC;CACpEI,UAAU,EACRC,MAAM;EACJC,SAAS;;EAETC,SAAS;CACX,EACF;CACAC,iBAAiB,EACfH,MAAM,UACR;AACF,CAAC;AAED,SAAgBgB,SAAST,OAAoD;CAC3E,MAAM,CAACC,OAAOC,QAAQf,WAAWa,OAAO,CAAC,QAAQ,OAAO,CAAC;CAEzD,cAAA;EAAA,IAAAU,QAAAC,QAAA;EAAAN,OAAAK,OAAAJ,WAAA,EAAA,KAAA,WAAA;GAAA,OAGWhB,GAAGkB,iBAAiB,EAAEf,MAAMQ,MAAMR,KAAK,CAAC,GAAGQ,MAAMM,KAAK;EAAC,EAAA,GAC1DL,IAAI,GAAA,OAAA,KAAA;EAAA,OAAAQ;CAAA,EAAA,CAAA;AAGd;;;;;;AAOA,SAAgBE,aAAaC,MAAwB;CACnD,OAAO,CAAC,GAAGA,IAAI;AACjB;;;;;;;;;AAgBA,SAAgBG,SAAShB,OAAsB;CAC7C,MAAM,CAACC,OAAOC,QAAQf,WAAWa,OAAO;EAAC;EAAQ;EAAQ;CAAO,CAAC;CAEjE,OAAAiB,gBACGR,UAAQH,WAAKJ,MAAI;EAAA,IAAET,OAAI;GAAA,OAAEQ,MAAMR;EAAI;EAAA,KAAA,WAAA;GAAA,OAASQ,MAAMM;EAAK;EAAA,eAAA;EAAA,IAAAW,WAAA;GAAA,OAAAD,gBACrD/B,KAAG;IAAA,IAACiC,OAAI;KAAA,OAAEP,aAAaX,MAAMY,IAAI;IAAC;IAAAK,WAAIE,QAAGH,gBAAMlB,KAAG;KAAA,IAACN,OAAI;MAAA,OAAEQ,MAAMR;KAAI;KAAAyB,UAAGE;IAAG,CAAA;GAAO,CAAA;EAAA;CAAA,CAAA,CAAA;AAGvF"}
|
package/dist/index.js
CHANGED
|
@@ -42,7 +42,7 @@ import { Item, ItemDescription, ItemEmpty, ItemGroup, ItemGroupEntry, ItemTitle,
|
|
|
42
42
|
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText } from "./components/ui/input-group/input-group.js";
|
|
43
43
|
import { SecretInputGroup } from "./components/ui/input-group/secret-input-group.js";
|
|
44
44
|
import { InputOtp, InputOtpCaret } from "./components/ui/input-otp/input-otp.js";
|
|
45
|
-
import { Kbd, KbdGroup } from "./components/ui/kbd/kbd.js";
|
|
45
|
+
import { Kbd, KbdChord, KbdGroup, kbdChordKeys, kbdGroupVariants, kbdVariants } from "./components/ui/kbd/kbd.js";
|
|
46
46
|
import { Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger } from "./components/ui/menubar/menubar.js";
|
|
47
47
|
import { ModalDialog } from "./components/ui/modal-dialog/modal-dialog.js";
|
|
48
48
|
import { NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuGroupLabel, NavigationMenuItem, NavigationMenuMenu, NavigationMenuSeparator, NavigationMenuTrigger, NavigationMenuViewport } from "./components/ui/navigation-menu/navigation-menu.js";
|
|
@@ -68,7 +68,8 @@ import { Toggle, toggleVariants } from "./components/ui/toggle/toggle.js";
|
|
|
68
68
|
import { ToggleGroup, ToggleGroupItem } from "./components/ui/toggle-group/toggle-group.js";
|
|
69
69
|
import { Presence } from "./components/motion/presence.js";
|
|
70
70
|
import { Motion } from "./components/motion/index.js";
|
|
71
|
-
import { MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO,
|
|
71
|
+
import { MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, countLeaves, layoutDepth, listLeaves } from "./components/layout/split-layout/tree.js";
|
|
72
|
+
import { closePane, createLayoutState, focusPane, movePane, neighborLeaf, normalizeLayout, resizeSplit, splitPane, swapPanes, undoClosePane } from "./components/layout/split-layout/model.js";
|
|
72
73
|
import { computeLayoutFrames } from "./components/layout/split-layout/geometry.js";
|
|
73
74
|
import { SplitLayout } from "./components/layout/split-layout/split-layout.js";
|
|
74
75
|
import { FLOATING_PREVIEW_CORNER_RADIUS, FLOATING_PREVIEW_EDGE_GAP, NO_FLOATING_PREVIEW_OBSTACLES, NO_PREVIEW_MINI_PLAYER_OBSTACLES, PREVIEW_MINI_PLAYER_CORNER_RADIUS, PREVIEW_MINI_PLAYER_EDGE_GAP, clampFloatingPreviewPosition, clampPreviewMiniPlayerPosition, resizeFloatingPreview, resizePreviewMiniPlayer, resolveFloatingPreviewFrame, resolvePreviewMiniPlayerFrame } from "./components/layout/floating-preview/model.js";
|
|
@@ -122,4 +123,4 @@ import { AboutDialog } from "./components/composites/about-dialog/about-dialog.j
|
|
|
122
123
|
import { HelpCenter } from "./components/composites/help-center/help-center.js";
|
|
123
124
|
import { WorkspaceMark } from "./components/composites/workspace-mark/workspace-mark.js";
|
|
124
125
|
import { writeClipboardText } from "./lib/clipboard.js";
|
|
125
|
-
export { AboutDialog, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AccountMenu, ActionButton, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, AppShellBody, AppShellContent, AppShellMain, AppearanceEditor, AppearancePanel, AppearancePopover, AspectRatio, AttachmentCard, Avatar, AvatarFallback, AvatarImage, Badge, Board, BoardCardBody, BoardCardTitle, BoardCardTrigger, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbSeparator, BusySendButton, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CalendarSurface, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CatalogBrowser, CatalogDetail, CatalogDetailSection, ChatComposer, Checkbox, CheckboxDescription, CheckboxLabel, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxClear, ComboboxContent, ComboboxControl, ComboboxInput, ComboboxItem, ComboboxSection, ComboboxTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, ComposerAttachmentButton, ComposerHint, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ConversationAvatar, ConversationSurface, DatePicker, DetailPanel, DetailPanelBody, DetailPanelField, DetailPanelHeader, DetailPanelSection, Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffBlock, DiffSummary, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, EntityIcon, FLOATING_PREVIEW_CORNER_RADIUS, FLOATING_PREVIEW_EDGE_GAP, Field, FieldDescription, FieldError, FieldGroup, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, FloatingPreview, FormField, Heading, HelpCenter, HoverCard, HoverCardContent, HoverCardTrigger, InlineCode, Input, InputControl, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputOtp, InputOtpCaret, Item, ItemDescription, ItemEmpty, ItemGroup, ItemGroupEntry, ItemTitle, Kbd, KbdGroup, Label, ListGroup, ListRow, ListRowControl, MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, ModalDialog, Motion, NO_FLOATING_PREVIEW_OBSTACLES, NO_PREVIEW_MINI_PLAYER_OBSTACLES, NativeSelect, NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuGroupLabel, NavigationMenuItem, NavigationMenuMenu, NavigationMenuSeparator, NavigationMenuTrigger, NavigationMenuViewport, NumberField, OrbitItem, OrbitLayout, PASTE_THRESHOLD_CHARS, PASTE_THRESHOLD_LINES, PASTE_TOKEN_REGEX, PREVIEW_MINI_PLAYER_CORNER_RADIUS, PREVIEW_MINI_PLAYER_EDGE_GAP, Page, PageHeader, PageHeaderActions, PageHeaderContent, PageHeaderDescription, PageHeaderTitle, PageSection, Pagination, PaginationEllipsis, PaginationItem, PaginationNext, PaginationPrevious, PalettePreview, Panel, PanelActions, PanelBody, PanelCard, PanelDescription, PanelFooter, PanelHeader, PanelPlaceholder, PanelTitle, PanelToolbar, Popover, PopoverAnchor, PopoverCloseButton, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger, Presence, Progress, PropertyList, PropertyRow, PropertyTerm, PropertyValue, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, SceneControls, ScrollArea, SecretInputGroup, Select, SelectChevronsUpDown, SelectContent, SelectItem, SelectLabel, SelectSection, SelectTrigger, SelectValue, Separator, SettingsField, SettingsLayout, SettingsNavigation, SettingsPage, SettingsRow, SettingsSection, Sheet, SheetBody, SheetCloseButton, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, SideRail, SideRailButton, SideRailContent, SideRailFooter, SideRailHeader, SideRailItem, SideRailSection, SidebarNav, SidebarNavButton, SidebarNavContent, SidebarNavFooter, SidebarNavHeader, SidebarNavItem, SidebarNavLabel, SidebarNavResizeHandle, SidebarNavRow, SidebarNavSection, SidebarNavTitle, Skeleton, SkipLink, Slider, Spinner, SplitLayout, Stat, StatGroup, StatusBar, StatusBarItem, StatusBarSpacer, StatusChip, StatusList, Switch, SwitchDescription, SwitchLabel, TALL_CODE_BLOCK_PX, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableNumericCell, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Text, TextLink, Textarea, ThemeMiniature, ThemeMiniatureSplit, ThemeModeToggle, ThemePicker, ThemePreview, ThemeProvider, ThemeSwatch, ThemeToggle, ThreadPanel, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopBar, TopBarBreadcrumb, TopBarPill, TopBarSearch, TopBarSection, TopBarTitle, TranscriptComposition, Tree, TreeRow, UpdateDialog, ValueCombobox, VirtualWindow, WorkspaceMark, accentPresets, alertVariants, allTokens, appearancePreviewThemes, badgeVariants, boardCardTitleVariants, builtinThemes, buttonVariants, clampFloatingPreviewPosition, clampPreviewMiniPlayerPosition, closePane, cn, colorTokens, computeLayoutFrames, contrastRatio, controlInteractive, controlSize, controlSizeIcon, controlSizes, countLeaves, countLines, createAppMenuItems, createLayoutState, cva, defaultDarkThemeId, defaultLightThemeId, defaultThemeSelection, densityTokens, designTokens, diffLineVariants, diffStats, diffTargetPath, elevationTokens, entityIconVariants, expandAll, findTokenRanges, focusPane, fontOptions, formatBytes, formatReleaseDate, formatToken, headingElement, headingVariants, initialsFrom, inlineScriptLiteral, isPasteBlock, isThemeAccentId, itemVariants, keyedRows, layoutDepth, listLeaves, monogram, motionTokens, movePane, neighborLeaf, nextSeq, normalizeLayout, parseDiff, plainTextFromMarkdown, pruneBlocks, radiusTokens, recollapsePastes, remapCarriedBlocks, resizeFloatingPreview, resizePreviewMiniPlayer, resizeSplit, resolveAccentPreset, resolveFloatingPreviewFrame, resolvePreviewMiniPlayerFrame, resolvedDensity, sheetVariants, shouldCollapse, sidebarNavItemClass, sidebarNavItemStateClass, splitPane, statusDotVariants, stripTrailingBlankLines, surfaceInteractive, swapPanes, textElement, textVariants, textareaVariants, themeAccentsFor, themeById, themeCssVariables, themeFamilies, themeRecordById, themeRecords, themeScript, themesForAppearance, toast, toaster, toggleVariants, tokenRangeAt, transcriptDisclosureKey, typographyTokens, undoClosePane, undocumentedTokenAliases, useSideRail, useTheme, validateTheme, validateThemeRegistry, withAccent, writeClipboardText, zIndexTokens };
|
|
126
|
+
export { AboutDialog, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AccountMenu, ActionButton, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, AppShellBody, AppShellContent, AppShellMain, AppearanceEditor, AppearancePanel, AppearancePopover, AspectRatio, AttachmentCard, Avatar, AvatarFallback, AvatarImage, Badge, Board, BoardCardBody, BoardCardTitle, BoardCardTrigger, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbSeparator, BusySendButton, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CalendarSurface, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CatalogBrowser, CatalogDetail, CatalogDetailSection, ChatComposer, Checkbox, CheckboxDescription, CheckboxLabel, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxClear, ComboboxContent, ComboboxControl, ComboboxInput, ComboboxItem, ComboboxSection, ComboboxTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandLoading, CommandSeparator, CommandShortcut, ComposerAttachmentButton, ComposerHint, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ConversationAvatar, ConversationSurface, DatePicker, DetailPanel, DetailPanelBody, DetailPanelField, DetailPanelHeader, DetailPanelSection, Dialog, DialogClose, DialogCloseButton, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffBlock, DiffSummary, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, EntityIcon, FLOATING_PREVIEW_CORNER_RADIUS, FLOATING_PREVIEW_EDGE_GAP, Field, FieldDescription, FieldError, FieldGroup, FieldInput, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTextArea, FloatingPreview, FormField, Heading, HelpCenter, HoverCard, HoverCardContent, HoverCardTrigger, InlineCode, Input, InputControl, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputOtp, InputOtpCaret, Item, ItemDescription, ItemEmpty, ItemGroup, ItemGroupEntry, ItemTitle, Kbd, KbdChord, KbdGroup, Label, ListGroup, ListRow, ListRowControl, MAX_LAYOUT_DEPTH, MAX_LAYOUT_LEAVES, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MessageBody, MessageComposer, MessageDayDivider, MessageGroup, MessageRow, ModalDialog, Motion, NO_FLOATING_PREVIEW_OBSTACLES, NO_PREVIEW_MINI_PLAYER_OBSTACLES, NativeSelect, NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuGroupLabel, NavigationMenuItem, NavigationMenuMenu, NavigationMenuSeparator, NavigationMenuTrigger, NavigationMenuViewport, NumberField, OrbitItem, OrbitLayout, PASTE_THRESHOLD_CHARS, PASTE_THRESHOLD_LINES, PASTE_TOKEN_REGEX, PREVIEW_MINI_PLAYER_CORNER_RADIUS, PREVIEW_MINI_PLAYER_EDGE_GAP, Page, PageHeader, PageHeaderActions, PageHeaderContent, PageHeaderDescription, PageHeaderTitle, PageSection, Pagination, PaginationEllipsis, PaginationItem, PaginationNext, PaginationPrevious, PalettePreview, Panel, PanelActions, PanelBody, PanelCard, PanelDescription, PanelFooter, PanelHeader, PanelPlaceholder, PanelTitle, PanelToolbar, Popover, PopoverAnchor, PopoverCloseButton, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger, Presence, Progress, PropertyList, PropertyRow, PropertyTerm, PropertyValue, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, SceneControls, ScrollArea, SecretInputGroup, Select, SelectChevronsUpDown, SelectContent, SelectItem, SelectLabel, SelectSection, SelectTrigger, SelectValue, Separator, SettingsField, SettingsLayout, SettingsNavigation, SettingsPage, SettingsRow, SettingsSection, Sheet, SheetBody, SheetCloseButton, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, SideRail, SideRailButton, SideRailContent, SideRailFooter, SideRailHeader, SideRailItem, SideRailSection, SidebarNav, SidebarNavButton, SidebarNavContent, SidebarNavFooter, SidebarNavHeader, SidebarNavItem, SidebarNavLabel, SidebarNavResizeHandle, SidebarNavRow, SidebarNavSection, SidebarNavTitle, Skeleton, SkipLink, Slider, Spinner, SplitLayout, Stat, StatGroup, StatusBar, StatusBarItem, StatusBarSpacer, StatusChip, StatusList, Switch, SwitchDescription, SwitchLabel, TALL_CODE_BLOCK_PX, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableNumericCell, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Text, TextLink, Textarea, ThemeMiniature, ThemeMiniatureSplit, ThemeModeToggle, ThemePicker, ThemePreview, ThemeProvider, ThemeSwatch, ThemeToggle, ThreadPanel, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopBar, TopBarBreadcrumb, TopBarPill, TopBarSearch, TopBarSection, TopBarTitle, TranscriptComposition, Tree, TreeRow, UpdateDialog, ValueCombobox, VirtualWindow, WorkspaceMark, accentPresets, alertVariants, allTokens, appearancePreviewThemes, badgeVariants, boardCardTitleVariants, builtinThemes, buttonVariants, clampFloatingPreviewPosition, clampPreviewMiniPlayerPosition, closePane, cn, colorTokens, computeLayoutFrames, contrastRatio, controlInteractive, controlSize, controlSizeIcon, controlSizes, countLeaves, countLines, createAppMenuItems, createLayoutState, cva, defaultDarkThemeId, defaultLightThemeId, defaultThemeSelection, densityTokens, designTokens, diffLineVariants, diffStats, diffTargetPath, elevationTokens, entityIconVariants, expandAll, findTokenRanges, focusPane, fontOptions, formatBytes, formatReleaseDate, formatToken, headingElement, headingVariants, initialsFrom, inlineScriptLiteral, isPasteBlock, isThemeAccentId, itemVariants, kbdChordKeys, kbdGroupVariants, kbdVariants, keyedRows, layoutDepth, listLeaves, monogram, motionTokens, movePane, neighborLeaf, nextSeq, normalizeLayout, parseDiff, plainTextFromMarkdown, pruneBlocks, radiusTokens, recollapsePastes, remapCarriedBlocks, resizeFloatingPreview, resizePreviewMiniPlayer, resizeSplit, resolveAccentPreset, resolveFloatingPreviewFrame, resolvePreviewMiniPlayerFrame, resolvedDensity, sheetVariants, shouldCollapse, sidebarNavItemClass, sidebarNavItemStateClass, splitPane, statusDotVariants, stripTrailingBlankLines, surfaceInteractive, swapPanes, textElement, textVariants, textareaVariants, themeAccentsFor, themeById, themeCssVariables, themeFamilies, themeRecordById, themeRecords, themeScript, themesForAppearance, toast, toaster, toggleVariants, tokenRangeAt, transcriptDisclosureKey, typographyTokens, undoClosePane, undocumentedTokenAliases, useSideRail, useTheme, validateTheme, validateThemeRegistry, withAccent, writeClipboardText, zIndexTokens };
|
package/dist/r/about-dialog.json
CHANGED
package/dist/r/accordion.json
CHANGED
package/dist/r/account-menu.json
CHANGED
package/dist/r/alert.json
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
"title": "Appearance Editor",
|
|
5
5
|
"description": "",
|
|
6
6
|
"dependencies": [
|
|
7
|
-
"@adea-ai/themes@^0.9.
|
|
7
|
+
"@adea-ai/themes@^0.9.6",
|
|
8
8
|
"@kobalte/core@^0.13.14",
|
|
9
|
-
"lucide-solid@^1.
|
|
9
|
+
"lucide-solid@^1.51.0"
|
|
10
10
|
],
|
|
11
11
|
"registryDependencies": [
|
|
12
12
|
"@adea-ai/ui/button",
|