@lattice-php/lattice 0.23.0 → 0.24.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/types/generated.d.ts +2 -19
- package/dist/ui/plugin.js +1 -3
- package/dist/ui/plugin.js.map +1 -1
- package/dist/vite.js +2 -1
- package/dist/vite.js.map +1 -1
- package/dist-standalone/lattice.css +1 -1
- package/dist-standalone/lattice.js +2 -2
- package/dist-standalone/manifest.json +2 -2
- package/package.json +1 -1
- package/dist/ui/tree-context.d.ts +0 -33
- package/dist/ui/tree-context.js +0 -135
- package/dist/ui/tree-context.js.map +0 -1
- package/dist/ui/tree.d.ts +0 -19
- package/dist/ui/tree.js +0 -187
- package/dist/ui/tree.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.24.0",
|
|
3
3
|
"files": {
|
|
4
|
-
"lattice.js": "
|
|
4
|
+
"lattice.js": "de39e3025b4d",
|
|
5
5
|
"chunks/chart-view-DEwGTt9d.js": "3e80210cc3d7",
|
|
6
6
|
"chunks/date-picker-field-CCQ9nWx0.js": "d97e934b112d",
|
|
7
7
|
"chunks/dist-PaT1gYi_.js": "4da471d00496",
|
package/package.json
CHANGED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { RefObject } from 'react';
|
|
2
|
-
export type TreeItemRegistration = {
|
|
3
|
-
id: string;
|
|
4
|
-
label: string;
|
|
5
|
-
orderPath: string;
|
|
6
|
-
parentPath: string | null;
|
|
7
|
-
path: string;
|
|
8
|
-
ref: RefObject<HTMLLIElement | null>;
|
|
9
|
-
};
|
|
10
|
-
export type TreeFocusDirection = "first" | "firstChild" | "last" | "next" | "parent" | "prev";
|
|
11
|
-
export type TreeContextValue = {
|
|
12
|
-
activate: (id: string) => void;
|
|
13
|
-
activeId: string | null;
|
|
14
|
-
expanded: Set<string>;
|
|
15
|
-
focus: (id: string) => void;
|
|
16
|
-
focusedId: string | null;
|
|
17
|
-
moveFocus: (fromId: string, direction: TreeFocusDirection) => void;
|
|
18
|
-
register: (entry: TreeItemRegistration) => void;
|
|
19
|
-
toggle: (id: string) => void;
|
|
20
|
-
typeAhead: (fromId: string, character: string) => void;
|
|
21
|
-
unregister: (path: string) => void;
|
|
22
|
-
};
|
|
23
|
-
export declare const TreeContext: import('react').Context<TreeContextValue>;
|
|
24
|
-
export declare function useTreeContext(): TreeContextValue;
|
|
25
|
-
export declare function useTreeState({ activeId: initialActiveId, defaultExpanded, nodes, rememberState, storageKey, }: {
|
|
26
|
-
activeId: string | null;
|
|
27
|
-
defaultExpanded: string[];
|
|
28
|
-
nodes: Array<{
|
|
29
|
-
id: string;
|
|
30
|
-
}>;
|
|
31
|
-
rememberState: boolean;
|
|
32
|
-
storageKey: string;
|
|
33
|
-
}): TreeContextValue;
|
package/dist/ui/tree-context.js
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { usePersistentState } from "../lib/use-persistent-state.js";
|
|
2
|
-
import { createContext, useCallback, useContext, useMemo, useRef, useState } from "react";
|
|
3
|
-
var TreeContext = createContext({
|
|
4
|
-
activate: () => {},
|
|
5
|
-
activeId: null,
|
|
6
|
-
expanded: /* @__PURE__ */ new Set(),
|
|
7
|
-
focus: () => {},
|
|
8
|
-
focusedId: null,
|
|
9
|
-
moveFocus: () => {},
|
|
10
|
-
register: () => {},
|
|
11
|
-
toggle: () => {},
|
|
12
|
-
typeAhead: () => {},
|
|
13
|
-
unregister: () => {}
|
|
14
|
-
});
|
|
15
|
-
function useTreeContext() {
|
|
16
|
-
return useContext(TreeContext);
|
|
17
|
-
}
|
|
18
|
-
function parseExpanded(raw) {
|
|
19
|
-
const parsed = JSON.parse(raw);
|
|
20
|
-
if (!Array.isArray(parsed)) throw new Error("expected an array of ids");
|
|
21
|
-
return new Set(parsed.filter((id) => typeof id === "string"));
|
|
22
|
-
}
|
|
23
|
-
function visibleOrder(registry) {
|
|
24
|
-
return [...registry.values()].sort((a, b) => a.orderPath.localeCompare(b.orderPath));
|
|
25
|
-
}
|
|
26
|
-
var TYPEAHEAD_IDLE_MS = 800;
|
|
27
|
-
function useTreeState({ activeId: initialActiveId, defaultExpanded, nodes, rememberState, storageKey }) {
|
|
28
|
-
const [expanded, setExpanded] = usePersistentState(storageKey, () => new Set(defaultExpanded), {
|
|
29
|
-
enabled: rememberState,
|
|
30
|
-
parse: parseExpanded,
|
|
31
|
-
serialize: (value) => JSON.stringify([...value])
|
|
32
|
-
});
|
|
33
|
-
const [activeId, setActiveId] = useState(initialActiveId);
|
|
34
|
-
const [focusedId, setFocusedId] = useState(() => nodes[0]?.id ?? null);
|
|
35
|
-
const registryRef = useRef(/* @__PURE__ */ new Map());
|
|
36
|
-
const typeAheadRef = useRef({
|
|
37
|
-
text: "",
|
|
38
|
-
timestamp: 0
|
|
39
|
-
});
|
|
40
|
-
const toggle = useCallback((id) => {
|
|
41
|
-
setExpanded((current) => {
|
|
42
|
-
const next = new Set(current);
|
|
43
|
-
if (next.has(id)) next.delete(id);
|
|
44
|
-
else next.add(id);
|
|
45
|
-
return next;
|
|
46
|
-
});
|
|
47
|
-
}, [setExpanded]);
|
|
48
|
-
const activate = useCallback((id) => setActiveId(id), []);
|
|
49
|
-
const focus = useCallback((id) => {
|
|
50
|
-
setFocusedId(id);
|
|
51
|
-
[...registryRef.current.values()].find((candidate) => candidate.id === id)?.ref.current?.focus();
|
|
52
|
-
}, []);
|
|
53
|
-
const register = useCallback((entry) => {
|
|
54
|
-
registryRef.current.set(entry.path, entry);
|
|
55
|
-
}, []);
|
|
56
|
-
const unregister = useCallback((path) => {
|
|
57
|
-
registryRef.current.delete(path);
|
|
58
|
-
}, []);
|
|
59
|
-
const moveFocus = useCallback((fromId, direction) => {
|
|
60
|
-
const order = visibleOrder(registryRef.current);
|
|
61
|
-
if (order.length === 0) return;
|
|
62
|
-
const index = order.findIndex((entry) => entry.id === fromId);
|
|
63
|
-
const current = index === -1 ? void 0 : order[index];
|
|
64
|
-
let target;
|
|
65
|
-
switch (direction) {
|
|
66
|
-
case "next":
|
|
67
|
-
target = index === -1 ? void 0 : order[index + 1];
|
|
68
|
-
break;
|
|
69
|
-
case "prev":
|
|
70
|
-
target = index === -1 ? void 0 : order[index - 1];
|
|
71
|
-
break;
|
|
72
|
-
case "first":
|
|
73
|
-
target = order[0];
|
|
74
|
-
break;
|
|
75
|
-
case "last":
|
|
76
|
-
target = order[order.length - 1];
|
|
77
|
-
break;
|
|
78
|
-
case "parent":
|
|
79
|
-
target = current ? order.find((entry) => entry.path === current.parentPath) : void 0;
|
|
80
|
-
break;
|
|
81
|
-
case "firstChild":
|
|
82
|
-
target = current ? order.find((entry) => entry.parentPath === current.path) : void 0;
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
if (target) focus(target.id);
|
|
86
|
-
}, [focus]);
|
|
87
|
-
const typeAhead = useCallback((fromId, character) => {
|
|
88
|
-
const order = visibleOrder(registryRef.current);
|
|
89
|
-
if (order.length === 0) return;
|
|
90
|
-
const now = Date.now();
|
|
91
|
-
const buffer = typeAheadRef.current;
|
|
92
|
-
const text = now - buffer.timestamp > TYPEAHEAD_IDLE_MS ? character : buffer.text + character;
|
|
93
|
-
typeAheadRef.current = {
|
|
94
|
-
text,
|
|
95
|
-
timestamp: now
|
|
96
|
-
};
|
|
97
|
-
const needle = text.toLowerCase();
|
|
98
|
-
const startIndex = order.findIndex((entry) => entry.id === fromId);
|
|
99
|
-
const start = startIndex === -1 ? 0 : startIndex;
|
|
100
|
-
for (let offset = 1; offset <= order.length; offset++) {
|
|
101
|
-
const candidate = order[(start + offset) % order.length];
|
|
102
|
-
if (candidate.label.toLowerCase().startsWith(needle)) {
|
|
103
|
-
focus(candidate.id);
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}, [focus]);
|
|
108
|
-
return useMemo(() => ({
|
|
109
|
-
activate,
|
|
110
|
-
activeId,
|
|
111
|
-
expanded,
|
|
112
|
-
focus,
|
|
113
|
-
focusedId,
|
|
114
|
-
moveFocus,
|
|
115
|
-
register,
|
|
116
|
-
toggle,
|
|
117
|
-
typeAhead,
|
|
118
|
-
unregister
|
|
119
|
-
}), [
|
|
120
|
-
activate,
|
|
121
|
-
activeId,
|
|
122
|
-
expanded,
|
|
123
|
-
focus,
|
|
124
|
-
focusedId,
|
|
125
|
-
moveFocus,
|
|
126
|
-
register,
|
|
127
|
-
toggle,
|
|
128
|
-
typeAhead,
|
|
129
|
-
unregister
|
|
130
|
-
]);
|
|
131
|
-
}
|
|
132
|
-
//#endregion
|
|
133
|
-
export { TreeContext, useTreeContext, useTreeState };
|
|
134
|
-
|
|
135
|
-
//# sourceMappingURL=tree-context.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tree-context.js","names":[],"sources":["../../resources/js/ui/tree-context.tsx"],"sourcesContent":["import { createContext, useCallback, useContext, useMemo, useRef, useState } from \"react\";\nimport type { RefObject } from \"react\";\nimport { usePersistentState } from \"@lattice-php/lattice/lib/use-persistent-state\";\n\nexport type TreeItemRegistration = {\n id: string;\n label: string;\n orderPath: string;\n parentPath: string | null;\n path: string;\n ref: RefObject<HTMLLIElement | null>;\n};\n\nexport type TreeFocusDirection = \"first\" | \"firstChild\" | \"last\" | \"next\" | \"parent\" | \"prev\";\n\nexport type TreeContextValue = {\n activate: (id: string) => void;\n activeId: string | null;\n expanded: Set<string>;\n focus: (id: string) => void;\n focusedId: string | null;\n moveFocus: (fromId: string, direction: TreeFocusDirection) => void;\n register: (entry: TreeItemRegistration) => void;\n toggle: (id: string) => void;\n typeAhead: (fromId: string, character: string) => void;\n unregister: (path: string) => void;\n};\n\nconst defaultTreeContext: TreeContextValue = {\n activate: () => {},\n activeId: null,\n expanded: new Set(),\n focus: () => {},\n focusedId: null,\n moveFocus: () => {},\n register: () => {},\n toggle: () => {},\n typeAhead: () => {},\n unregister: () => {},\n};\n\nexport const TreeContext = createContext<TreeContextValue>(defaultTreeContext);\n\nexport function useTreeContext(): TreeContextValue {\n return useContext(TreeContext);\n}\n\nfunction parseExpanded(raw: string): Set<string> {\n const parsed: unknown = JSON.parse(raw);\n\n if (!Array.isArray(parsed)) {\n throw new Error(\"expected an array of ids\");\n }\n\n return new Set(parsed.filter((id): id is string => typeof id === \"string\"));\n}\n\nfunction visibleOrder(registry: Map<string, TreeItemRegistration>): TreeItemRegistration[] {\n return [...registry.values()].sort((a, b) => a.orderPath.localeCompare(b.orderPath));\n}\n\nconst TYPEAHEAD_IDLE_MS = 800;\n\nexport function useTreeState({\n activeId: initialActiveId,\n defaultExpanded,\n nodes,\n rememberState,\n storageKey,\n}: {\n activeId: string | null;\n defaultExpanded: string[];\n nodes: Array<{ id: string }>;\n rememberState: boolean;\n storageKey: string;\n}): TreeContextValue {\n const [expanded, setExpanded] = usePersistentState<Set<string>>(\n storageKey,\n () => new Set(defaultExpanded),\n {\n enabled: rememberState,\n parse: parseExpanded,\n serialize: (value) => JSON.stringify([...value]),\n },\n );\n const [activeId, setActiveId] = useState<string | null>(initialActiveId);\n const [focusedId, setFocusedId] = useState<string | null>(() => nodes[0]?.id ?? null);\n const registryRef = useRef<Map<string, TreeItemRegistration>>(new Map());\n const typeAheadRef = useRef<{ text: string; timestamp: number }>({ text: \"\", timestamp: 0 });\n\n const toggle = useCallback(\n (id: string) => {\n setExpanded((current) => {\n const next = new Set(current);\n\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n\n return next;\n });\n },\n [setExpanded],\n );\n\n const activate = useCallback((id: string) => setActiveId(id), []);\n\n const focus = useCallback((id: string) => {\n setFocusedId(id);\n const entry = [...registryRef.current.values()].find((candidate) => candidate.id === id);\n entry?.ref.current?.focus();\n }, []);\n\n const register = useCallback((entry: TreeItemRegistration) => {\n registryRef.current.set(entry.path, entry);\n }, []);\n\n const unregister = useCallback((path: string) => {\n registryRef.current.delete(path);\n }, []);\n\n const moveFocus = useCallback(\n (fromId: string, direction: TreeFocusDirection) => {\n const order = visibleOrder(registryRef.current);\n\n if (order.length === 0) {\n return;\n }\n\n const index = order.findIndex((entry) => entry.id === fromId);\n const current = index === -1 ? undefined : order[index];\n\n let target: TreeItemRegistration | undefined;\n\n switch (direction) {\n case \"next\":\n target = index === -1 ? undefined : order[index + 1];\n break;\n case \"prev\":\n target = index === -1 ? undefined : order[index - 1];\n break;\n case \"first\":\n target = order[0];\n break;\n case \"last\":\n target = order[order.length - 1];\n break;\n case \"parent\":\n target = current ? order.find((entry) => entry.path === current.parentPath) : undefined;\n break;\n case \"firstChild\":\n target = current ? order.find((entry) => entry.parentPath === current.path) : undefined;\n break;\n }\n\n if (target) {\n focus(target.id);\n }\n },\n [focus],\n );\n\n const typeAhead = useCallback(\n (fromId: string, character: string) => {\n const order = visibleOrder(registryRef.current);\n\n if (order.length === 0) {\n return;\n }\n\n const now = Date.now();\n const buffer = typeAheadRef.current;\n const text = now - buffer.timestamp > TYPEAHEAD_IDLE_MS ? character : buffer.text + character;\n typeAheadRef.current = { text, timestamp: now };\n\n const needle = text.toLowerCase();\n const startIndex = order.findIndex((entry) => entry.id === fromId);\n const start = startIndex === -1 ? 0 : startIndex;\n\n for (let offset = 1; offset <= order.length; offset++) {\n const candidate = order[(start + offset) % order.length];\n\n if (candidate.label.toLowerCase().startsWith(needle)) {\n focus(candidate.id);\n return;\n }\n }\n },\n [focus],\n );\n\n return useMemo(\n () => ({\n activate,\n activeId,\n expanded,\n focus,\n focusedId,\n moveFocus,\n register,\n toggle,\n typeAhead,\n unregister,\n }),\n [\n activate,\n activeId,\n expanded,\n focus,\n focusedId,\n moveFocus,\n register,\n toggle,\n typeAhead,\n unregister,\n ],\n );\n}\n"],"mappings":"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"}
|
package/dist/ui/tree.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { RendererComponent } from '../core/types.js';
|
|
2
|
-
import { Tree as TreeProps, TreeNode as GeneratedTreeNode } from '../types/generated.js';
|
|
3
|
-
/**
|
|
4
|
-
* The actual sparse wire shape a tree node serializes as (see `TreeNode::jsonSerialize()`):
|
|
5
|
-
* every optional/falsy field is omitted rather than sent as `null`/`false`, unlike the
|
|
6
|
-
* generated `TreeNode`, which reflects every declared PHP property as required.
|
|
7
|
-
*/
|
|
8
|
-
export type TreeNodeData = Pick<GeneratedTreeNode, "id" | "label"> & Partial<Omit<GeneratedTreeNode, "children" | "id" | "label">> & {
|
|
9
|
-
children?: TreeNodeData[];
|
|
10
|
-
};
|
|
11
|
-
declare module '../core/types' {
|
|
12
|
-
interface ComponentProps {
|
|
13
|
-
tree: TreeProps & {
|
|
14
|
-
nodes: TreeNodeData[];
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
declare const TreeComponent: RendererComponent<"tree">;
|
|
19
|
-
export default TreeComponent;
|
package/dist/ui/tree.js
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import { useT } from "../i18n/instance.js";
|
|
2
|
-
import { cn } from "../lib/utils.js";
|
|
3
|
-
import { Icon } from "../icons/sprite.js";
|
|
4
|
-
import { IconRenderer } from "../icons/icon-renderer.js";
|
|
5
|
-
import { Renderer } from "../core/renderer.js";
|
|
6
|
-
import { nodeIdentity } from "../core/test-id.js";
|
|
7
|
-
import { Badge } from "./badge.js";
|
|
8
|
-
import { TextLink } from "./link.js";
|
|
9
|
-
import { TreeContext, useTreeContext, useTreeState } from "./tree-context.js";
|
|
10
|
-
import { router } from "@inertiajs/react";
|
|
11
|
-
import { useEffect, useRef } from "react";
|
|
12
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
-
//#region resources/js/ui/tree.tsx
|
|
14
|
-
function hasExpandableChildren(node) {
|
|
15
|
-
return Boolean(node.children?.length) || node.hasChildren === true;
|
|
16
|
-
}
|
|
17
|
-
var ORDER_PATH_SEGMENT_WIDTH = 6;
|
|
18
|
-
function orderPathSegment(index) {
|
|
19
|
-
return String(index).padStart(ORDER_PATH_SEGMENT_WIDTH, "0");
|
|
20
|
-
}
|
|
21
|
-
function TreeItem({ depth, node, orderPath, parentPath, siblingCount, siblingIndex }) {
|
|
22
|
-
const { activate, activeId, expanded, focusedId, moveFocus, register, toggle, typeAhead, unregister } = useTreeContext();
|
|
23
|
-
const { t } = useT("lattice");
|
|
24
|
-
const ref = useRef(null);
|
|
25
|
-
const path = parentPath ? `${parentPath}/${node.id}` : node.id;
|
|
26
|
-
const isExpanded = expanded.has(node.id);
|
|
27
|
-
const isActive = activeId === node.id;
|
|
28
|
-
const isFocused = focusedId === node.id;
|
|
29
|
-
const isDisabled = node.disabled === true;
|
|
30
|
-
const expandable = hasExpandableChildren(node);
|
|
31
|
-
const actionsRef = useRef(null);
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
register({
|
|
34
|
-
id: node.id,
|
|
35
|
-
label: node.label,
|
|
36
|
-
orderPath,
|
|
37
|
-
parentPath,
|
|
38
|
-
path,
|
|
39
|
-
ref
|
|
40
|
-
});
|
|
41
|
-
return () => unregister(path);
|
|
42
|
-
}, [
|
|
43
|
-
node.id,
|
|
44
|
-
node.label,
|
|
45
|
-
orderPath,
|
|
46
|
-
parentPath,
|
|
47
|
-
path,
|
|
48
|
-
register,
|
|
49
|
-
unregister
|
|
50
|
-
]);
|
|
51
|
-
useEffect(() => {
|
|
52
|
-
const container = actionsRef.current;
|
|
53
|
-
if (!container) return;
|
|
54
|
-
container.querySelectorAll("button, a[href], [tabindex]").forEach((control) => {
|
|
55
|
-
control.tabIndex = -1;
|
|
56
|
-
});
|
|
57
|
-
}, [node.actions]);
|
|
58
|
-
function onKeyDown(event) {
|
|
59
|
-
if (event.target !== event.currentTarget) return;
|
|
60
|
-
switch (event.key) {
|
|
61
|
-
case "ArrowDown":
|
|
62
|
-
event.preventDefault();
|
|
63
|
-
moveFocus(node.id, "next");
|
|
64
|
-
return;
|
|
65
|
-
case "ArrowUp":
|
|
66
|
-
event.preventDefault();
|
|
67
|
-
moveFocus(node.id, "prev");
|
|
68
|
-
return;
|
|
69
|
-
case "ArrowRight":
|
|
70
|
-
event.preventDefault();
|
|
71
|
-
if (expandable && !isExpanded) toggle(node.id);
|
|
72
|
-
else if (expandable) moveFocus(node.id, "firstChild");
|
|
73
|
-
return;
|
|
74
|
-
case "ArrowLeft":
|
|
75
|
-
event.preventDefault();
|
|
76
|
-
if (expandable && isExpanded) toggle(node.id);
|
|
77
|
-
else moveFocus(node.id, "parent");
|
|
78
|
-
return;
|
|
79
|
-
case "Home":
|
|
80
|
-
event.preventDefault();
|
|
81
|
-
moveFocus(node.id, "first");
|
|
82
|
-
return;
|
|
83
|
-
case "End":
|
|
84
|
-
event.preventDefault();
|
|
85
|
-
moveFocus(node.id, "last");
|
|
86
|
-
return;
|
|
87
|
-
case "Enter":
|
|
88
|
-
case " ":
|
|
89
|
-
event.preventDefault();
|
|
90
|
-
if (isDisabled) return;
|
|
91
|
-
if (node.href) router.visit(node.href);
|
|
92
|
-
else if (node.actions) {
|
|
93
|
-
actionsRef.current?.querySelector("button")?.click();
|
|
94
|
-
ref.current?.focus();
|
|
95
|
-
} else activate(node.id);
|
|
96
|
-
return;
|
|
97
|
-
default: if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) typeAhead(node.id, event.key);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return /* @__PURE__ */ jsxs("li", {
|
|
101
|
-
"aria-disabled": isDisabled,
|
|
102
|
-
"aria-expanded": expandable ? isExpanded : void 0,
|
|
103
|
-
"aria-level": depth,
|
|
104
|
-
"aria-posinset": siblingIndex,
|
|
105
|
-
"aria-selected": isActive,
|
|
106
|
-
"aria-setsize": siblingCount,
|
|
107
|
-
"data-test": `tree-node-${node.id}`,
|
|
108
|
-
onKeyDown,
|
|
109
|
-
ref,
|
|
110
|
-
role: "treeitem",
|
|
111
|
-
tabIndex: isFocused ? 0 : -1,
|
|
112
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
113
|
-
className: cn("flex items-center gap-2 rounded-lt-sm px-2 py-1.5 text-sm text-lt-fg", isActive && "bg-lt-muted font-medium", isDisabled && "pointer-events-none opacity-50"),
|
|
114
|
-
children: [
|
|
115
|
-
expandable ? /* @__PURE__ */ jsx("button", {
|
|
116
|
-
"aria-label": isExpanded ? t("common.tree.collapse", "Collapse {{label}}", { label: node.label }) : t("common.tree.expand", "Expand {{label}}", { label: node.label }),
|
|
117
|
-
"data-test": `tree-node-${node.id}-toggle`,
|
|
118
|
-
onClick: () => toggle(node.id),
|
|
119
|
-
tabIndex: -1,
|
|
120
|
-
type: "button",
|
|
121
|
-
children: /* @__PURE__ */ jsx(Icon, {
|
|
122
|
-
className: cn("size-lt-icon-md shrink-0 transition-transform", isExpanded && "rotate-90"),
|
|
123
|
-
name: "chevron-right"
|
|
124
|
-
})
|
|
125
|
-
}) : null,
|
|
126
|
-
node.icon ? /* @__PURE__ */ jsx(IconRenderer, {
|
|
127
|
-
className: "size-lt-icon-md shrink-0",
|
|
128
|
-
icon: node.icon
|
|
129
|
-
}) : null,
|
|
130
|
-
node.href && !isDisabled ? /* @__PURE__ */ jsx(TextLink, {
|
|
131
|
-
href: node.href,
|
|
132
|
-
tabIndex: -1,
|
|
133
|
-
children: node.label
|
|
134
|
-
}) : /* @__PURE__ */ jsx("span", { children: node.label }),
|
|
135
|
-
node.badge ? /* @__PURE__ */ jsx(Badge, {
|
|
136
|
-
variant: "secondary",
|
|
137
|
-
children: node.badge
|
|
138
|
-
}) : null,
|
|
139
|
-
node.actions ? /* @__PURE__ */ jsx("span", {
|
|
140
|
-
className: "ml-auto",
|
|
141
|
-
ref: actionsRef,
|
|
142
|
-
children: /* @__PURE__ */ jsx(Renderer, { nodes: [node.actions] })
|
|
143
|
-
}) : null
|
|
144
|
-
]
|
|
145
|
-
}), expandable && isExpanded && node.children && node.children.length > 0 ? /* @__PURE__ */ jsx("ul", {
|
|
146
|
-
className: "pl-6",
|
|
147
|
-
role: "group",
|
|
148
|
-
children: node.children.map((child, index) => /* @__PURE__ */ jsx(TreeItem, {
|
|
149
|
-
depth: depth + 1,
|
|
150
|
-
node: child,
|
|
151
|
-
orderPath: `${orderPath}.${orderPathSegment(index)}`,
|
|
152
|
-
parentPath: path,
|
|
153
|
-
siblingCount: node.children?.length ?? 1,
|
|
154
|
-
siblingIndex: index + 1
|
|
155
|
-
}, child.id))
|
|
156
|
-
}) : null]
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
var TreeComponent = ({ node }) => {
|
|
160
|
-
const identity = nodeIdentity(node);
|
|
161
|
-
const value = useTreeState({
|
|
162
|
-
activeId: node.props.activeId,
|
|
163
|
-
defaultExpanded: node.props.defaultExpanded,
|
|
164
|
-
nodes: node.props.nodes,
|
|
165
|
-
rememberState: node.props.rememberState,
|
|
166
|
-
storageKey: `lattice:tree:${identity ?? "default"}`
|
|
167
|
-
});
|
|
168
|
-
return /* @__PURE__ */ jsx(TreeContext.Provider, {
|
|
169
|
-
value,
|
|
170
|
-
children: /* @__PURE__ */ jsx("ul", {
|
|
171
|
-
"data-lattice-component": identity,
|
|
172
|
-
role: "tree",
|
|
173
|
-
children: node.props.nodes.map((child, index) => /* @__PURE__ */ jsx(TreeItem, {
|
|
174
|
-
depth: 1,
|
|
175
|
-
node: child,
|
|
176
|
-
orderPath: orderPathSegment(index),
|
|
177
|
-
parentPath: null,
|
|
178
|
-
siblingCount: node.props.nodes.length,
|
|
179
|
-
siblingIndex: index + 1
|
|
180
|
-
}, child.id))
|
|
181
|
-
})
|
|
182
|
-
});
|
|
183
|
-
};
|
|
184
|
-
//#endregion
|
|
185
|
-
export { TreeComponent as default };
|
|
186
|
-
|
|
187
|
-
//# sourceMappingURL=tree.js.map
|
package/dist/ui/tree.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tree.js","names":[],"sources":["../../resources/js/ui/tree.tsx"],"sourcesContent":["import { router } from \"@inertiajs/react\";\nimport { useEffect, useRef } from \"react\";\nimport type { KeyboardEvent } from \"react\";\nimport { Renderer } from \"@lattice-php/lattice/core/renderer\";\nimport { nodeIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { Icon, IconRenderer } from \"@lattice-php/lattice/icons\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type {\n Tree as TreeProps,\n TreeNode as GeneratedTreeNode,\n} from \"@lattice-php/lattice/types/generated\";\nimport { Badge } from \"./badge\";\nimport { TextLink } from \"./link\";\nimport { TreeContext, useTreeContext, useTreeState } from \"./tree-context\";\n\n/**\n * The actual sparse wire shape a tree node serializes as (see `TreeNode::jsonSerialize()`):\n * every optional/falsy field is omitted rather than sent as `null`/`false`, unlike the\n * generated `TreeNode`, which reflects every declared PHP property as required.\n */\nexport type TreeNodeData = Pick<GeneratedTreeNode, \"id\" | \"label\"> &\n Partial<Omit<GeneratedTreeNode, \"children\" | \"id\" | \"label\">> & {\n children?: TreeNodeData[];\n };\n\ndeclare module \"@lattice-php/lattice/core/types\" {\n interface ComponentProps {\n tree: TreeProps & { nodes: TreeNodeData[] };\n }\n}\n\nfunction hasExpandableChildren(node: TreeNodeData): boolean {\n return Boolean(node.children?.length) || node.hasChildren === true;\n}\n\nconst ORDER_PATH_SEGMENT_WIDTH = 6;\n\nfunction orderPathSegment(index: number): string {\n return String(index).padStart(ORDER_PATH_SEGMENT_WIDTH, \"0\");\n}\n\nfunction TreeItem({\n depth,\n node,\n orderPath,\n parentPath,\n siblingCount,\n siblingIndex,\n}: {\n depth: number;\n node: TreeNodeData;\n orderPath: string;\n parentPath: string | null;\n siblingCount: number;\n siblingIndex: number;\n}) {\n const {\n activate,\n activeId,\n expanded,\n focusedId,\n moveFocus,\n register,\n toggle,\n typeAhead,\n unregister,\n } = useTreeContext();\n const { t } = useT(\"lattice\");\n const ref = useRef<HTMLLIElement>(null);\n const path = parentPath ? `${parentPath}/${node.id}` : node.id;\n const isExpanded = expanded.has(node.id);\n const isActive = activeId === node.id;\n const isFocused = focusedId === node.id;\n const isDisabled = node.disabled === true;\n const expandable = hasExpandableChildren(node);\n const actionsRef = useRef<HTMLSpanElement>(null);\n\n useEffect(() => {\n register({ id: node.id, label: node.label, orderPath, parentPath, path, ref });\n\n return () => unregister(path);\n }, [node.id, node.label, orderPath, parentPath, path, register, unregister]);\n\n useEffect(() => {\n const container = actionsRef.current;\n\n if (!container) {\n return;\n }\n\n container.querySelectorAll<HTMLElement>(\"button, a[href], [tabindex]\").forEach((control) => {\n control.tabIndex = -1;\n });\n }, [node.actions]);\n\n function onKeyDown(event: KeyboardEvent<HTMLLIElement>): void {\n if (event.target !== event.currentTarget) {\n return;\n }\n\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n moveFocus(node.id, \"next\");\n return;\n case \"ArrowUp\":\n event.preventDefault();\n moveFocus(node.id, \"prev\");\n return;\n case \"ArrowRight\":\n event.preventDefault();\n if (expandable && !isExpanded) {\n toggle(node.id);\n } else if (expandable) {\n moveFocus(node.id, \"firstChild\");\n }\n return;\n case \"ArrowLeft\":\n event.preventDefault();\n if (expandable && isExpanded) {\n toggle(node.id);\n } else {\n moveFocus(node.id, \"parent\");\n }\n return;\n case \"Home\":\n event.preventDefault();\n moveFocus(node.id, \"first\");\n return;\n case \"End\":\n event.preventDefault();\n moveFocus(node.id, \"last\");\n return;\n case \"Enter\":\n case \" \":\n event.preventDefault();\n if (isDisabled) {\n return;\n }\n if (node.href) {\n router.visit(node.href);\n } else if (node.actions) {\n actionsRef.current?.querySelector(\"button\")?.click();\n ref.current?.focus();\n } else {\n activate(node.id);\n }\n return;\n default:\n if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {\n typeAhead(node.id, event.key);\n }\n }\n }\n\n return (\n <li\n aria-disabled={isDisabled}\n aria-expanded={expandable ? isExpanded : undefined}\n aria-level={depth}\n aria-posinset={siblingIndex}\n aria-selected={isActive}\n aria-setsize={siblingCount}\n data-test={`tree-node-${node.id}`}\n onKeyDown={onKeyDown}\n ref={ref}\n role=\"treeitem\"\n tabIndex={isFocused ? 0 : -1}\n >\n <div\n className={cn(\n \"flex items-center gap-2 rounded-lt-sm px-2 py-1.5 text-sm text-lt-fg\",\n isActive && \"bg-lt-muted font-medium\",\n isDisabled && \"pointer-events-none opacity-50\",\n )}\n >\n {expandable ? (\n <button\n aria-label={\n isExpanded\n ? t(\"common.tree.collapse\", \"Collapse {{label}}\", { label: node.label })\n : t(\"common.tree.expand\", \"Expand {{label}}\", { label: node.label })\n }\n data-test={`tree-node-${node.id}-toggle`}\n onClick={() => toggle(node.id)}\n tabIndex={-1}\n type=\"button\"\n >\n <Icon\n className={cn(\n \"size-lt-icon-md shrink-0 transition-transform\",\n isExpanded && \"rotate-90\",\n )}\n name=\"chevron-right\"\n />\n </button>\n ) : null}\n {node.icon ? <IconRenderer className=\"size-lt-icon-md shrink-0\" icon={node.icon} /> : null}\n {node.href && !isDisabled ? (\n <TextLink href={node.href} tabIndex={-1}>\n {node.label}\n </TextLink>\n ) : (\n <span>{node.label}</span>\n )}\n {node.badge ? <Badge variant=\"secondary\">{node.badge}</Badge> : null}\n {node.actions ? (\n <span className=\"ml-auto\" ref={actionsRef}>\n <Renderer nodes={[node.actions]} />\n </span>\n ) : null}\n </div>\n {expandable && isExpanded && node.children && node.children.length > 0 ? (\n <ul className=\"pl-6\" role=\"group\">\n {node.children.map((child, index) => (\n <TreeItem\n depth={depth + 1}\n key={child.id}\n node={child}\n orderPath={`${orderPath}.${orderPathSegment(index)}`}\n parentPath={path}\n siblingCount={node.children?.length ?? 1}\n siblingIndex={index + 1}\n />\n ))}\n </ul>\n ) : null}\n </li>\n );\n}\n\nconst TreeComponent: RendererComponent<\"tree\"> = ({ node }) => {\n const identity = nodeIdentity(node);\n const value = useTreeState({\n activeId: node.props.activeId,\n defaultExpanded: node.props.defaultExpanded,\n nodes: node.props.nodes,\n rememberState: node.props.rememberState,\n storageKey: `lattice:tree:${identity ?? \"default\"}`,\n });\n\n return (\n <TreeContext.Provider value={value}>\n <ul data-lattice-component={identity} role=\"tree\">\n {node.props.nodes.map((child, index) => (\n <TreeItem\n depth={1}\n key={child.id}\n node={child}\n orderPath={orderPathSegment(index)}\n parentPath={null}\n siblingCount={node.props.nodes.length}\n siblingIndex={index + 1}\n />\n ))}\n </ul>\n </TreeContext.Provider>\n );\n};\n\nexport default TreeComponent;\n"],"mappings":"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"}
|