@xenosystem/blocks 0.16.0 → 0.17.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/dist/edit/index.d.ts +25 -5
- package/dist/edit/index.js +27 -4
- package/package.json +1 -1
package/dist/edit/index.d.ts
CHANGED
|
@@ -1199,9 +1199,10 @@ declare function fieldMatches(field: XenoInspectorField, term: string): boolean;
|
|
|
1199
1199
|
/**
|
|
1200
1200
|
* Project a schema into renderable sections.
|
|
1201
1201
|
*
|
|
1202
|
-
* Visibility-by-data: a section is dropped entirely when it has no matching fields AND
|
|
1203
|
-
* `emptyHint` — the panel never renders an empty box the
|
|
1204
|
-
*
|
|
1202
|
+
* Visibility-by-data: a section is dropped entirely when it has no matching fields AND nothing to
|
|
1203
|
+
* act on — no `emptyHint`, no `actions`, no `addMenu` — the panel never renders an empty box the
|
|
1204
|
+
* user cannot act on. (An action-only section — Canvas's align strip — IS something to act on.)
|
|
1205
|
+
* While a filter is active, fieldless sections are dropped regardless (they are not search results).
|
|
1205
1206
|
*/
|
|
1206
1207
|
declare function projectSections(schema: XenoInspectorSchema, options?: ProjectOptions$1): ProjectedSection[];
|
|
1207
1208
|
/** Whether a section is collapsed, honoring `defaultCollapsed` for sections the user never touched. */
|
|
@@ -6755,6 +6756,11 @@ interface XenoTreeGlyph {
|
|
|
6755
6756
|
* and another names lucide icons. A single `icon: string` field forces every consumer to guess
|
|
6756
6757
|
* which it is holding, and guessing renders `'📄'` as a missing-icon box.
|
|
6757
6758
|
*/
|
|
6759
|
+
/** What a node carries when dragged out of the panel (see `XenoTreeNode.dragOut`). */
|
|
6760
|
+
interface XenoTreeDragOut {
|
|
6761
|
+
kind: string;
|
|
6762
|
+
payload?: unknown;
|
|
6763
|
+
}
|
|
6758
6764
|
type XenoTreeIcon = {
|
|
6759
6765
|
kind: 'lucide';
|
|
6760
6766
|
name: string;
|
|
@@ -6841,6 +6847,15 @@ interface XenoTreeNode {
|
|
|
6841
6847
|
columns?: Record<string, string>;
|
|
6842
6848
|
/** Hover actions. */
|
|
6843
6849
|
actions?: XenoTreeAction[];
|
|
6850
|
+
/**
|
|
6851
|
+
* The node may be dragged OUT of the panel and dropped on the host's own surface — a library
|
|
6852
|
+
* component onto a canvas, a clip onto a timeline. `kind` is the host's vocabulary word
|
|
6853
|
+
* (`'component'`, `'clip'`); `payload` is carried back verbatim on the `dragOut` output. The drag
|
|
6854
|
+
* itself is the panel's pointer drag: when it is released outside the panel's rows, the panel
|
|
6855
|
+
* emits `dragOut` with the release point and the host decides what a drop there means. A node
|
|
6856
|
+
* without this is only reorderable inside the tree.
|
|
6857
|
+
*/
|
|
6858
|
+
dragOut?: XenoTreeDragOut;
|
|
6844
6859
|
/**
|
|
6845
6860
|
* A stable identity for the *thing* this node points at — a resolved real path, an inode, a
|
|
6846
6861
|
* document id.
|
|
@@ -7360,14 +7375,19 @@ declare class TreeController {
|
|
|
7360
7375
|
/** Update the hovered drop target. */
|
|
7361
7376
|
dragOver(targetId: string, offsetY: number): DropPosition;
|
|
7362
7377
|
/**
|
|
7363
|
-
* Complete the drag, emitting a `move` intent when the drop is legal
|
|
7378
|
+
* Complete the drag, emitting a `move` intent when the drop is legal — or, when the release was
|
|
7379
|
+
* OUTSIDE the panel (`outside` given) and every dragged node declares `dragOut` of one kind, a
|
|
7380
|
+
* `dragOut` event carrying the release point for the host to hit-test.
|
|
7364
7381
|
*
|
|
7365
7382
|
* A refused drop emits **nothing** — and the refusal that matters most is the descendant one,
|
|
7366
7383
|
* which lives in `@xenosystem/tree-core` because two shipping apps delete a whole subtree without it.
|
|
7367
7384
|
*
|
|
7368
7385
|
* @returns `true` if a move intent was emitted.
|
|
7369
7386
|
*/
|
|
7370
|
-
endDrag(
|
|
7387
|
+
endDrag(outside?: {
|
|
7388
|
+
clientX: number;
|
|
7389
|
+
clientY: number;
|
|
7390
|
+
}): boolean;
|
|
7371
7391
|
/** Abandon the drag. */
|
|
7372
7392
|
cancelDrag(): void;
|
|
7373
7393
|
/** Descendants of a node, through the shared recursive walk. */
|
package/dist/edit/index.js
CHANGED
|
@@ -1970,7 +1970,8 @@ function projectSections(schema, options = {}) {
|
|
|
1970
1970
|
for (const section of schema.sections) {
|
|
1971
1971
|
const fields = filtering ? section.fields.filter((f) => fieldMatches(f, term)) : section.fields;
|
|
1972
1972
|
const empty = fields.length === 0;
|
|
1973
|
-
|
|
1973
|
+
const actionable = !!section.emptyHint || (section.actions?.length ?? 0) > 0 || (section.addMenu?.length ?? 0) > 0;
|
|
1974
|
+
if (empty && (filtering || !actionable)) continue;
|
|
1974
1975
|
const collapsed = !filtering && !!section.collapsible && isCollapsed(section, collapsedSet);
|
|
1975
1976
|
out.push({
|
|
1976
1977
|
section,
|
|
@@ -13113,16 +13114,29 @@ var TreeController = class {
|
|
|
13113
13114
|
return result.position;
|
|
13114
13115
|
}
|
|
13115
13116
|
/**
|
|
13116
|
-
* Complete the drag, emitting a `move` intent when the drop is legal
|
|
13117
|
+
* Complete the drag, emitting a `move` intent when the drop is legal — or, when the release was
|
|
13118
|
+
* OUTSIDE the panel (`outside` given) and every dragged node declares `dragOut` of one kind, a
|
|
13119
|
+
* `dragOut` event carrying the release point for the host to hit-test.
|
|
13117
13120
|
*
|
|
13118
13121
|
* A refused drop emits **nothing** — and the refusal that matters most is the descendant one,
|
|
13119
13122
|
* which lives in `@xenosystem/tree-core` because two shipping apps delete a whole subtree without it.
|
|
13120
13123
|
*
|
|
13121
13124
|
* @returns `true` if a move intent was emitted.
|
|
13122
13125
|
*/
|
|
13123
|
-
endDrag() {
|
|
13126
|
+
endDrag(outside) {
|
|
13124
13127
|
const drag = this.drag;
|
|
13125
13128
|
this.drag = null;
|
|
13129
|
+
if (drag && outside) {
|
|
13130
|
+
const nodes = drag.ids.map((id) => this.source?.nodes[id]).filter((n) => !!n);
|
|
13131
|
+
const outs = nodes.map((n) => n.dragOut).filter((d) => !!d);
|
|
13132
|
+
if (nodes.length > 0 && outs.length === nodes.length && outs.every((d) => d.kind === outs[0].kind)) {
|
|
13133
|
+
this.host.emit("dragOut", { ids: nodes.map((n) => n.id), kind: outs[0].kind, payloads: outs.map((d) => d.payload), clientX: outside.clientX, clientY: outside.clientY });
|
|
13134
|
+
this.notify();
|
|
13135
|
+
return true;
|
|
13136
|
+
}
|
|
13137
|
+
this.notify();
|
|
13138
|
+
return false;
|
|
13139
|
+
}
|
|
13126
13140
|
if (!drag || !drag.targetId || !drag.position) {
|
|
13127
13141
|
this.notify();
|
|
13128
13142
|
return false;
|
|
@@ -13247,6 +13261,12 @@ var treeManifest = {
|
|
|
13247
13261
|
schema: WELL_KNOWN_PORT_SCHEMAS8.TREE_OP,
|
|
13248
13262
|
description: "Everything the panel asks for \u2014 select, open, setExpanded, loadChildren, move, rename, create, delete, setProp, action. INTENTS ONLY: the host performs, pins ids, and pushes one undo entry."
|
|
13249
13263
|
},
|
|
13264
|
+
{
|
|
13265
|
+
id: "dragOut",
|
|
13266
|
+
name: "Dragged Out",
|
|
13267
|
+
type: "object",
|
|
13268
|
+
description: "{ ids, kind, payloads, clientX, clientY } \u2014 a pointer drag of nodes that declare `dragOut` was released OUTSIDE the panel. The host hit-tests its own surface at the point and performs the drop (place an instance, insert a clip); the panel places nothing. Nodes without `dragOut` never emit this."
|
|
13269
|
+
},
|
|
13250
13270
|
{
|
|
13251
13271
|
id: "selection",
|
|
13252
13272
|
name: "Selection",
|
|
@@ -13989,7 +14009,10 @@ function TreeScroller({ controller, children }) {
|
|
|
13989
14009
|
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
13990
14010
|
} catch {
|
|
13991
14011
|
}
|
|
13992
|
-
if (press?.dragging)
|
|
14012
|
+
if (!press?.dragging) return;
|
|
14013
|
+
const r = scrollRef.current?.getBoundingClientRect();
|
|
14014
|
+
const inside = !!r && e.clientX >= r.left && e.clientX <= r.right && e.clientY >= r.top && e.clientY <= r.bottom;
|
|
14015
|
+
controller.endDrag(inside ? void 0 : { clientX: e.clientX, clientY: e.clientY });
|
|
13993
14016
|
},
|
|
13994
14017
|
[controller]
|
|
13995
14018
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xenosystem/blocks",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "XENO Blocks — rung 3 of the front ladder: components composed into a contract-bearing unit (manifest: ports, intents, commands, agent surface), rendered by @xenosystem/workbench. ONE package, one subpath per family (/auth, /edit, /data, /time, /ops, /trust, /agent), one named export per block — XENO PACKAGE NAMING - STANDARD.md.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|