@woylie/doggo 0.16.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -21,7 +21,7 @@ The package can be installed by adding `doggo` to your list of dependencies in
21
21
  ```elixir
22
22
  def deps do
23
23
  [
24
- {:doggo, "~> 0.16.0"}
24
+ {:doggo, "~> 0.16.1"}
25
25
  ]
26
26
  end
27
27
  ```
@@ -10,7 +10,26 @@ const labelOf = (item) =>
10
10
  const parentOf = (item) =>
11
11
  item.parentElement.closest('[role="treeitem"]') || null;
12
12
 
13
- export function initTree(tree) {
13
+ const labelText = (item) => {
14
+ const label = labelOf(item);
15
+
16
+ if (!label) return "";
17
+
18
+ const copy = label.cloneNode(true);
19
+
20
+ for (const node of copy.querySelectorAll('[aria-hidden="true"], svg')) {
21
+ node.remove();
22
+ }
23
+
24
+ return copy.textContent;
25
+ };
26
+
27
+ const domWriter = {
28
+ setAttribute: (el, attr, value) => el.setAttribute(attr, value),
29
+ removeAttribute: (el, attr) => el.removeAttribute(attr),
30
+ };
31
+
32
+ export function initTree(tree, writer = domWriter) {
14
33
  // Visible items only. A collapsed branch takes its descendants out of the
15
34
  // sequence.
16
35
  const getItems = () =>
@@ -18,22 +37,6 @@ export function initTree(tree) {
18
37
  (item) => !item.closest('[role="group"][hidden]'),
19
38
  );
20
39
 
21
- // The hook owns the expanded state. A patch re-renders the server's
22
- // version, so it is remembered by position and applied again.
23
- const pathOf = (item) => {
24
- const path = [];
25
-
26
- for (let node = item; node; node = parentOf(node)) {
27
- const siblings = Array.from(
28
- node.parentElement.querySelectorAll(':scope > [role="treeitem"]'),
29
- );
30
- path.unshift(siblings.indexOf(node));
31
- }
32
-
33
- return path.join("-");
34
- };
35
-
36
- const expandedPaths = new Set();
37
40
  let activeIdx = 0;
38
41
  let search = "";
39
42
  let searchTimeout;
@@ -46,7 +49,7 @@ export function initTree(tree) {
46
49
  const active = getItems()[idx];
47
50
 
48
51
  for (const item of tree.querySelectorAll('[role="treeitem"]')) {
49
- item.setAttribute("tabindex", item === active ? "0" : "-1");
52
+ writer.setAttribute(item, "tabindex", item === active ? "0" : "-1");
50
53
  }
51
54
  };
52
55
 
@@ -56,25 +59,17 @@ export function initTree(tree) {
56
59
  };
57
60
 
58
61
  const setExpanded = (item, expanded) => {
59
- item.setAttribute("aria-expanded", expanded ? "true" : "false");
62
+ writer.setAttribute(item, "aria-expanded", expanded ? "true" : "false");
60
63
 
61
64
  const group = groupOf(item);
62
65
 
63
66
  if (group) {
64
67
  if (expanded) {
65
- group.removeAttribute("hidden");
68
+ writer.removeAttribute(group, "hidden");
66
69
  } else {
67
- group.setAttribute("hidden", "");
70
+ writer.setAttribute(group, "hidden", "");
68
71
  }
69
72
  }
70
-
71
- const path = pathOf(item);
72
-
73
- if (expanded) {
74
- expandedPaths.add(path);
75
- } else {
76
- expandedPaths.delete(path);
77
- }
78
73
  };
79
74
 
80
75
  // Only the caret toggles. A click on the label is the caller's, for
@@ -106,8 +101,7 @@ export function initTree(tree) {
106
101
 
107
102
  const repeated = [...search].every((char) => char === search[0]);
108
103
  const items = getItems();
109
- // The item's own label, but not nested items.
110
- const labels = items.map((item) => labelOf(item)?.textContent ?? "");
104
+ const labels = items.map(labelText);
111
105
  const idx = searchIndex(
112
106
  labels,
113
107
  repeated ? search[0] : search,
@@ -131,7 +125,7 @@ export function initTree(tree) {
131
125
  if (isBranch(item) && !isExpanded(item)) {
132
126
  setExpanded(item, true);
133
127
  } else if (isBranch(item)) {
134
- const child = groupOf(item).querySelector('[role="treeitem"]');
128
+ const child = groupOf(item)?.querySelector('[role="treeitem"]');
135
129
 
136
130
  if (child) moveTo(getItems().indexOf(child));
137
131
  }
@@ -155,6 +149,7 @@ export function initTree(tree) {
155
149
 
156
150
  const nextIdx = targetIndex(e.key, currentIdx, items.length, {
157
151
  orientation: "vertical",
152
+ wrap: false,
158
153
  });
159
154
 
160
155
  if (nextIdx !== null) {
@@ -170,12 +165,6 @@ export function initTree(tree) {
170
165
  });
171
166
 
172
167
  const restore = () => {
173
- for (const item of tree.querySelectorAll('[role="treeitem"]')) {
174
- if (isBranch(item) && expandedPaths.has(pathOf(item))) {
175
- setExpanded(item, true);
176
- }
177
- }
178
-
179
168
  const items = getItems();
180
169
 
181
170
  if (items.length > 0) setActive(clamp(activeIdx, items.length));
@@ -188,7 +177,12 @@ export function initTree(tree) {
188
177
 
189
178
  export default {
190
179
  mounted() {
191
- this.instance = initTree(this.el);
180
+ const js = this.js();
181
+
182
+ this.instance = initTree(this.el, {
183
+ setAttribute: (el, attr, value) => js.setAttribute(el, attr, value),
184
+ removeAttribute: (el, attr) => js.removeAttribute(el, attr),
185
+ });
192
186
  },
193
187
 
194
188
  updated() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@woylie/doggo",
3
- "version": "0.16.0",
3
+ "version": "0.16.1",
4
4
  "description": "JavaScript hooks for the Doggo component library",
5
5
  "keywords": [
6
6
  "phoenix",