@tanstack/devtools 0.5.0 → 0.6.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/esm/components/main-panel.js +8 -2
- package/dist/esm/components/main-panel.js.map +1 -1
- package/dist/esm/components/tabs.js +10 -0
- package/dist/esm/components/tabs.js.map +1 -1
- package/dist/esm/context/draw-context.d.ts +13 -0
- package/dist/esm/context/draw-context.js +55 -0
- package/dist/esm/context/draw-context.js.map +1 -0
- package/dist/esm/context/pip-context.js +1 -2
- package/dist/esm/context/pip-context.js.map +1 -1
- package/dist/esm/context/use-devtools-context.js +10 -1
- package/dist/esm/context/use-devtools-context.js.map +1 -1
- package/dist/esm/hooks/use-head-changes.d.ts +39 -0
- package/dist/esm/hooks/use-head-changes.js +65 -0
- package/dist/esm/hooks/use-head-changes.js.map +1 -0
- package/dist/esm/styles/tokens.js +4 -1
- package/dist/esm/styles/tokens.js.map +1 -1
- package/dist/esm/styles/use-styles.d.ts +19 -0
- package/dist/esm/styles/use-styles.js +143 -3
- package/dist/esm/styles/use-styles.js.map +1 -1
- package/dist/esm/tabs/index.d.ts +5 -0
- package/dist/esm/tabs/index.js +8 -2
- package/dist/esm/tabs/index.js.map +1 -1
- package/dist/esm/tabs/plugins-tab.js +31 -13
- package/dist/esm/tabs/plugins-tab.js.map +1 -1
- package/dist/esm/tabs/seo-tab.d.ts +1 -0
- package/dist/esm/tabs/seo-tab.js +291 -0
- package/dist/esm/tabs/seo-tab.js.map +1 -0
- package/package.json +1 -1
- package/src/components/main-panel.tsx +5 -1
- package/src/components/tabs.tsx +9 -0
- package/src/context/draw-context.tsx +67 -0
- package/src/context/pip-context.tsx +1 -3
- package/src/context/use-devtools-context.ts +12 -2
- package/src/hooks/use-head-changes.ts +110 -0
- package/src/styles/use-styles.ts +148 -3
- package/src/tabs/index.tsx +25 -0
- package/src/tabs/plugins-tab.tsx +51 -23
- package/src/tabs/seo-tab.tsx +238 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { template, insert, createComponent, memo, effect, className, setAttribute } from "solid-js/web";
|
|
2
|
+
import { createSignal, For } from "solid-js";
|
|
3
|
+
import { useStyles } from "../styles/use-styles.js";
|
|
4
|
+
import { useHeadChanges } from "../hooks/use-head-changes.js";
|
|
5
|
+
var _tmpl$ = /* @__PURE__ */ template(`<div><div> Preview</div><div></div><div></div><div>`), _tmpl$2 = /* @__PURE__ */ template(`<img alt=Preview>`), _tmpl$3 = /* @__PURE__ */ template(`<div>No Image`), _tmpl$4 = /* @__PURE__ */ template(`<div><section><h3><svg xmlns=http://www.w3.org/2000/svg width=24 height=24 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round><path d="m10 9-3 3 3 3"></path><path d="m14 15 3-3-3-3"></path><path d="M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"></path></svg>Social previews</h3><p>See how your current page will look when shared on popular social networks. The tool checks for essential meta tags and highlights any that are missing.</p><div>`), _tmpl$5 = /* @__PURE__ */ template(`<div>`), _tmpl$6 = /* @__PURE__ */ template(`<div><strong>Missing tags for <!>:</strong><ul>`), _tmpl$7 = /* @__PURE__ */ template(`<li>`);
|
|
6
|
+
const SOCIALS = [
|
|
7
|
+
{
|
|
8
|
+
network: "Facebook",
|
|
9
|
+
tags: [{
|
|
10
|
+
key: "og:title",
|
|
11
|
+
prop: "title"
|
|
12
|
+
}, {
|
|
13
|
+
key: "og:description",
|
|
14
|
+
prop: "description"
|
|
15
|
+
}, {
|
|
16
|
+
key: "og:image",
|
|
17
|
+
prop: "image"
|
|
18
|
+
}, {
|
|
19
|
+
key: "og:url",
|
|
20
|
+
prop: "url"
|
|
21
|
+
}],
|
|
22
|
+
color: "#4267B2"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
network: "X/Twitter",
|
|
26
|
+
tags: [{
|
|
27
|
+
key: "twitter:title",
|
|
28
|
+
prop: "title"
|
|
29
|
+
}, {
|
|
30
|
+
key: "twitter:description",
|
|
31
|
+
prop: "description"
|
|
32
|
+
}, {
|
|
33
|
+
key: "twitter:image",
|
|
34
|
+
prop: "image"
|
|
35
|
+
}, {
|
|
36
|
+
key: "twitter:url",
|
|
37
|
+
prop: "url"
|
|
38
|
+
}],
|
|
39
|
+
color: "#1DA1F2"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
network: "LinkedIn",
|
|
43
|
+
tags: [{
|
|
44
|
+
key: "og:title",
|
|
45
|
+
prop: "title"
|
|
46
|
+
}, {
|
|
47
|
+
key: "og:description",
|
|
48
|
+
prop: "description"
|
|
49
|
+
}, {
|
|
50
|
+
key: "og:image",
|
|
51
|
+
prop: "image"
|
|
52
|
+
}, {
|
|
53
|
+
key: "og:url",
|
|
54
|
+
prop: "url"
|
|
55
|
+
}],
|
|
56
|
+
color: "#0077B5"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
network: "Discord",
|
|
60
|
+
tags: [{
|
|
61
|
+
key: "og:title",
|
|
62
|
+
prop: "title"
|
|
63
|
+
}, {
|
|
64
|
+
key: "og:description",
|
|
65
|
+
prop: "description"
|
|
66
|
+
}, {
|
|
67
|
+
key: "og:image",
|
|
68
|
+
prop: "image"
|
|
69
|
+
}, {
|
|
70
|
+
key: "og:url",
|
|
71
|
+
prop: "url"
|
|
72
|
+
}],
|
|
73
|
+
color: "#5865F2"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
network: "Slack",
|
|
77
|
+
tags: [{
|
|
78
|
+
key: "og:title",
|
|
79
|
+
prop: "title"
|
|
80
|
+
}, {
|
|
81
|
+
key: "og:description",
|
|
82
|
+
prop: "description"
|
|
83
|
+
}, {
|
|
84
|
+
key: "og:image",
|
|
85
|
+
prop: "image"
|
|
86
|
+
}, {
|
|
87
|
+
key: "og:url",
|
|
88
|
+
prop: "url"
|
|
89
|
+
}],
|
|
90
|
+
color: "#4A154B"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
network: "Mastodon",
|
|
94
|
+
tags: [{
|
|
95
|
+
key: "og:title",
|
|
96
|
+
prop: "title"
|
|
97
|
+
}, {
|
|
98
|
+
key: "og:description",
|
|
99
|
+
prop: "description"
|
|
100
|
+
}, {
|
|
101
|
+
key: "og:image",
|
|
102
|
+
prop: "image"
|
|
103
|
+
}, {
|
|
104
|
+
key: "og:url",
|
|
105
|
+
prop: "url"
|
|
106
|
+
}],
|
|
107
|
+
color: "#6364FF"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
network: "Bluesky",
|
|
111
|
+
tags: [{
|
|
112
|
+
key: "og:title",
|
|
113
|
+
prop: "title"
|
|
114
|
+
}, {
|
|
115
|
+
key: "og:description",
|
|
116
|
+
prop: "description"
|
|
117
|
+
}, {
|
|
118
|
+
key: "og:image",
|
|
119
|
+
prop: "image"
|
|
120
|
+
}, {
|
|
121
|
+
key: "og:url",
|
|
122
|
+
prop: "url"
|
|
123
|
+
}],
|
|
124
|
+
color: "#1185FE"
|
|
125
|
+
}
|
|
126
|
+
// Add more networks as needed
|
|
127
|
+
];
|
|
128
|
+
function SocialPreview(props) {
|
|
129
|
+
const styles = useStyles();
|
|
130
|
+
return (() => {
|
|
131
|
+
var _el$ = _tmpl$(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$4 = _el$2.nextSibling, _el$5 = _el$4.nextSibling, _el$6 = _el$5.nextSibling;
|
|
132
|
+
insert(_el$2, () => props.network, _el$3);
|
|
133
|
+
insert(_el$, (() => {
|
|
134
|
+
var _c$ = memo(() => !!props.meta.image);
|
|
135
|
+
return () => _c$() ? (() => {
|
|
136
|
+
var _el$7 = _tmpl$2();
|
|
137
|
+
effect((_p$) => {
|
|
138
|
+
var _v$8 = props.meta.image, _v$9 = styles().seoPreviewImage;
|
|
139
|
+
_v$8 !== _p$.e && setAttribute(_el$7, "src", _p$.e = _v$8);
|
|
140
|
+
_v$9 !== _p$.t && className(_el$7, _p$.t = _v$9);
|
|
141
|
+
return _p$;
|
|
142
|
+
}, {
|
|
143
|
+
e: void 0,
|
|
144
|
+
t: void 0
|
|
145
|
+
});
|
|
146
|
+
return _el$7;
|
|
147
|
+
})() : (() => {
|
|
148
|
+
var _el$8 = _tmpl$3();
|
|
149
|
+
_el$8.style.setProperty("background", "#222");
|
|
150
|
+
_el$8.style.setProperty("color", "#888");
|
|
151
|
+
_el$8.style.setProperty("display", "flex");
|
|
152
|
+
_el$8.style.setProperty("align-items", "center");
|
|
153
|
+
_el$8.style.setProperty("justify-content", "center");
|
|
154
|
+
_el$8.style.setProperty("min-height", "80px");
|
|
155
|
+
_el$8.style.setProperty("width", "100%");
|
|
156
|
+
effect(() => className(_el$8, styles().seoPreviewImage));
|
|
157
|
+
return _el$8;
|
|
158
|
+
})();
|
|
159
|
+
})(), _el$4);
|
|
160
|
+
insert(_el$4, () => props.meta.title || "No Title");
|
|
161
|
+
insert(_el$5, () => props.meta.description || "No Description");
|
|
162
|
+
insert(_el$6, () => props.meta.url || window.location.href);
|
|
163
|
+
effect((_p$) => {
|
|
164
|
+
var _v$ = styles().seoPreviewCard, _v$2 = props.color, _v$3 = styles().seoPreviewHeader, _v$4 = props.color, _v$5 = styles().seoPreviewTitle, _v$6 = styles().seoPreviewDesc, _v$7 = styles().seoPreviewUrl;
|
|
165
|
+
_v$ !== _p$.e && className(_el$, _p$.e = _v$);
|
|
166
|
+
_v$2 !== _p$.t && ((_p$.t = _v$2) != null ? _el$.style.setProperty("border-color", _v$2) : _el$.style.removeProperty("border-color"));
|
|
167
|
+
_v$3 !== _p$.a && className(_el$2, _p$.a = _v$3);
|
|
168
|
+
_v$4 !== _p$.o && ((_p$.o = _v$4) != null ? _el$2.style.setProperty("color", _v$4) : _el$2.style.removeProperty("color"));
|
|
169
|
+
_v$5 !== _p$.i && className(_el$4, _p$.i = _v$5);
|
|
170
|
+
_v$6 !== _p$.n && className(_el$5, _p$.n = _v$6);
|
|
171
|
+
_v$7 !== _p$.s && className(_el$6, _p$.s = _v$7);
|
|
172
|
+
return _p$;
|
|
173
|
+
}, {
|
|
174
|
+
e: void 0,
|
|
175
|
+
t: void 0,
|
|
176
|
+
a: void 0,
|
|
177
|
+
o: void 0,
|
|
178
|
+
i: void 0,
|
|
179
|
+
n: void 0,
|
|
180
|
+
s: void 0
|
|
181
|
+
});
|
|
182
|
+
return _el$;
|
|
183
|
+
})();
|
|
184
|
+
}
|
|
185
|
+
const SeoTab = () => {
|
|
186
|
+
const [reports, setReports] = createSignal(analyzeHead());
|
|
187
|
+
const styles = useStyles();
|
|
188
|
+
function analyzeHead() {
|
|
189
|
+
const metaTags = Array.from(document.head.querySelectorAll("meta"));
|
|
190
|
+
const reports2 = [];
|
|
191
|
+
for (const social of SOCIALS) {
|
|
192
|
+
const found = {};
|
|
193
|
+
const missing = [];
|
|
194
|
+
for (const tag of social.tags) {
|
|
195
|
+
const meta = metaTags.find((m) => (tag.key.includes("twitter:") ? false : m.getAttribute("property") === tag.key) || m.getAttribute("name") === tag.key);
|
|
196
|
+
if (meta && meta.getAttribute("content")) {
|
|
197
|
+
found[tag.prop] = meta.getAttribute("content") || void 0;
|
|
198
|
+
} else {
|
|
199
|
+
missing.push(tag.key);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
reports2.push({
|
|
203
|
+
network: social.network,
|
|
204
|
+
found,
|
|
205
|
+
missing
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return reports2;
|
|
209
|
+
}
|
|
210
|
+
useHeadChanges(() => {
|
|
211
|
+
setReports(analyzeHead());
|
|
212
|
+
});
|
|
213
|
+
return (() => {
|
|
214
|
+
var _el$9 = _tmpl$4(), _el$0 = _el$9.firstChild, _el$1 = _el$0.firstChild, _el$10 = _el$1.firstChild, _el$11 = _el$1.nextSibling, _el$12 = _el$11.nextSibling;
|
|
215
|
+
insert(_el$12, createComponent(For, {
|
|
216
|
+
get each() {
|
|
217
|
+
return reports();
|
|
218
|
+
},
|
|
219
|
+
children: (report, i) => {
|
|
220
|
+
const social = SOCIALS[i()];
|
|
221
|
+
return (() => {
|
|
222
|
+
var _el$13 = _tmpl$5();
|
|
223
|
+
insert(_el$13, createComponent(SocialPreview, {
|
|
224
|
+
get meta() {
|
|
225
|
+
return report.found;
|
|
226
|
+
},
|
|
227
|
+
get color() {
|
|
228
|
+
return social.color;
|
|
229
|
+
},
|
|
230
|
+
get network() {
|
|
231
|
+
return social.network;
|
|
232
|
+
}
|
|
233
|
+
}), null);
|
|
234
|
+
insert(_el$13, (() => {
|
|
235
|
+
var _c$2 = memo(() => report.missing.length > 0);
|
|
236
|
+
return () => _c$2() ? (() => {
|
|
237
|
+
var _el$14 = _tmpl$6(), _el$15 = _el$14.firstChild, _el$16 = _el$15.firstChild, _el$18 = _el$16.nextSibling;
|
|
238
|
+
_el$18.nextSibling;
|
|
239
|
+
var _el$19 = _el$15.nextSibling;
|
|
240
|
+
insert(_el$15, () => social?.network, _el$18);
|
|
241
|
+
insert(_el$19, createComponent(For, {
|
|
242
|
+
get each() {
|
|
243
|
+
return report.missing;
|
|
244
|
+
},
|
|
245
|
+
children: (tag) => (() => {
|
|
246
|
+
var _el$20 = _tmpl$7();
|
|
247
|
+
insert(_el$20, tag);
|
|
248
|
+
effect(() => className(_el$20, styles().seoMissingTag));
|
|
249
|
+
return _el$20;
|
|
250
|
+
})()
|
|
251
|
+
}));
|
|
252
|
+
effect((_p$) => {
|
|
253
|
+
var _v$14 = styles().seoMissingTagsSection, _v$15 = styles().seoMissingTagsList;
|
|
254
|
+
_v$14 !== _p$.e && className(_el$14, _p$.e = _v$14);
|
|
255
|
+
_v$15 !== _p$.t && className(_el$19, _p$.t = _v$15);
|
|
256
|
+
return _p$;
|
|
257
|
+
}, {
|
|
258
|
+
e: void 0,
|
|
259
|
+
t: void 0
|
|
260
|
+
});
|
|
261
|
+
return _el$14;
|
|
262
|
+
})() : null;
|
|
263
|
+
})(), null);
|
|
264
|
+
return _el$13;
|
|
265
|
+
})();
|
|
266
|
+
}
|
|
267
|
+
}));
|
|
268
|
+
effect((_p$) => {
|
|
269
|
+
var _v$0 = styles().seoTabContainer, _v$1 = styles().seoTabSection, _v$10 = styles().sectionTitle, _v$11 = styles().sectionIcon, _v$12 = styles().sectionDescription, _v$13 = styles().seoPreviewSection;
|
|
270
|
+
_v$0 !== _p$.e && className(_el$9, _p$.e = _v$0);
|
|
271
|
+
_v$1 !== _p$.t && className(_el$0, _p$.t = _v$1);
|
|
272
|
+
_v$10 !== _p$.a && className(_el$1, _p$.a = _v$10);
|
|
273
|
+
_v$11 !== _p$.o && setAttribute(_el$10, "class", _p$.o = _v$11);
|
|
274
|
+
_v$12 !== _p$.i && className(_el$11, _p$.i = _v$12);
|
|
275
|
+
_v$13 !== _p$.n && className(_el$12, _p$.n = _v$13);
|
|
276
|
+
return _p$;
|
|
277
|
+
}, {
|
|
278
|
+
e: void 0,
|
|
279
|
+
t: void 0,
|
|
280
|
+
a: void 0,
|
|
281
|
+
o: void 0,
|
|
282
|
+
i: void 0,
|
|
283
|
+
n: void 0
|
|
284
|
+
});
|
|
285
|
+
return _el$9;
|
|
286
|
+
})();
|
|
287
|
+
};
|
|
288
|
+
export {
|
|
289
|
+
SeoTab
|
|
290
|
+
};
|
|
291
|
+
//# sourceMappingURL=seo-tab.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-tab.js","sources":["../../../src/tabs/seo-tab.tsx"],"sourcesContent":["import { For, createSignal } from 'solid-js'\nimport { useStyles } from '../styles/use-styles'\nimport { useHeadChanges } from '../hooks/use-head-changes'\n\ntype SocialMeta = {\n title?: string\n description?: string\n image?: string\n url?: string\n}\n\ntype SocialReport = {\n network: string\n found: Partial<SocialMeta>\n missing: Array<string>\n}\n\nconst SOCIALS = [\n {\n network: 'Facebook',\n tags: [\n { key: 'og:title', prop: 'title' },\n { key: 'og:description', prop: 'description' },\n { key: 'og:image', prop: 'image' },\n { key: 'og:url', prop: 'url' },\n ],\n color: '#4267B2',\n },\n {\n network: 'X/Twitter',\n tags: [\n { key: 'twitter:title', prop: 'title' },\n { key: 'twitter:description', prop: 'description' },\n { key: 'twitter:image', prop: 'image' },\n { key: 'twitter:url', prop: 'url' },\n ],\n color: '#1DA1F2',\n },\n {\n network: 'LinkedIn',\n tags: [\n { key: 'og:title', prop: 'title' },\n { key: 'og:description', prop: 'description' },\n { key: 'og:image', prop: 'image' },\n { key: 'og:url', prop: 'url' },\n ],\n color: '#0077B5',\n },\n {\n network: 'Discord',\n tags: [\n { key: 'og:title', prop: 'title' },\n { key: 'og:description', prop: 'description' },\n { key: 'og:image', prop: 'image' },\n { key: 'og:url', prop: 'url' },\n ],\n color: '#5865F2',\n },\n {\n network: 'Slack',\n tags: [\n { key: 'og:title', prop: 'title' },\n { key: 'og:description', prop: 'description' },\n { key: 'og:image', prop: 'image' },\n { key: 'og:url', prop: 'url' },\n ],\n color: '#4A154B',\n },\n {\n network: 'Mastodon',\n tags: [\n { key: 'og:title', prop: 'title' },\n { key: 'og:description', prop: 'description' },\n { key: 'og:image', prop: 'image' },\n { key: 'og:url', prop: 'url' },\n ],\n color: '#6364FF',\n },\n {\n network: 'Bluesky',\n tags: [\n { key: 'og:title', prop: 'title' },\n { key: 'og:description', prop: 'description' },\n { key: 'og:image', prop: 'image' },\n { key: 'og:url', prop: 'url' },\n ],\n color: '#1185FE',\n },\n // Add more networks as needed\n]\nfunction SocialPreview(props: {\n meta: SocialMeta\n color: string\n network: string\n}) {\n const styles = useStyles()\n\n return (\n <div\n class={styles().seoPreviewCard}\n style={{ 'border-color': props.color }}\n >\n <div class={styles().seoPreviewHeader} style={{ color: props.color }}>\n {props.network} Preview\n </div>\n {props.meta.image ? (\n <img\n src={props.meta.image}\n alt=\"Preview\"\n class={styles().seoPreviewImage}\n />\n ) : (\n <div\n class={styles().seoPreviewImage}\n style={{\n background: '#222',\n color: '#888',\n display: 'flex',\n 'align-items': 'center',\n 'justify-content': 'center',\n 'min-height': '80px',\n width: '100%',\n }}\n >\n No Image\n </div>\n )}\n <div class={styles().seoPreviewTitle}>\n {props.meta.title || 'No Title'}\n </div>\n <div class={styles().seoPreviewDesc}>\n {props.meta.description || 'No Description'}\n </div>\n <div class={styles().seoPreviewUrl}>\n {props.meta.url || window.location.href}\n </div>\n </div>\n )\n}\nexport const SeoTab = () => {\n const [reports, setReports] = createSignal<Array<SocialReport>>(analyzeHead())\n const styles = useStyles()\n\n function analyzeHead(): Array<SocialReport> {\n const metaTags = Array.from(document.head.querySelectorAll('meta'))\n const reports: Array<SocialReport> = []\n\n for (const social of SOCIALS) {\n const found: Partial<SocialMeta> = {}\n const missing: Array<string> = []\n for (const tag of social.tags) {\n const meta = metaTags.find(\n (m) =>\n (tag.key.includes('twitter:')\n ? false\n : m.getAttribute('property') === tag.key) ||\n m.getAttribute('name') === tag.key,\n )\n\n if (meta && meta.getAttribute('content')) {\n found[tag.prop as keyof SocialMeta] =\n meta.getAttribute('content') || undefined\n } else {\n missing.push(tag.key)\n }\n }\n reports.push({ network: social.network, found, missing })\n }\n return reports\n }\n\n useHeadChanges(() => {\n setReports(analyzeHead())\n })\n\n return (\n <div class={styles().seoTabContainer}>\n <section class={styles().seoTabSection}>\n <h3 class={styles().sectionTitle}>\n <svg\n class={styles().sectionIcon}\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m10 9-3 3 3 3\" />\n <path d=\"m14 15 3-3-3-3\" />\n <path d=\"M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719\" />\n </svg>\n Social previews\n </h3>\n <p class={styles().sectionDescription}>\n See how your current page will look when shared on popular social\n networks. The tool checks for essential meta tags and highlights any\n that are missing.\n </p>\n <div class={styles().seoPreviewSection}>\n <For each={reports()}>\n {(report, i) => {\n const social = SOCIALS[i()]\n return (\n <div>\n <SocialPreview\n meta={report.found}\n color={social!.color}\n network={social!.network}\n />\n {report.missing.length > 0 ? (\n <>\n <div class={styles().seoMissingTagsSection}>\n <strong>Missing tags for {social?.network}:</strong>\n\n <ul class={styles().seoMissingTagsList}>\n <For each={report.missing}>\n {(tag) => (\n <li class={styles().seoMissingTag}>{tag}</li>\n )}\n </For>\n </ul>\n </div>\n </>\n ) : null}\n </div>\n )\n }}\n </For>\n </div>\n </section>\n {/* Future sections can be added here as <section class={styles().seoTabSection}>...</section> */}\n </div>\n )\n}\n"],"names":["SOCIALS","network","tags","key","prop","color","SocialPreview","props","styles","useStyles","_el$","_tmpl$","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$6","_$insert","_c$","_$memo","meta","image","_el$7","_tmpl$2","_$effect","_p$","_v$8","_v$9","seoPreviewImage","e","_$setAttribute","t","_$className","undefined","_el$8","_tmpl$3","style","setProperty","title","description","url","window","location","href","_v$","seoPreviewCard","_v$2","_v$3","seoPreviewHeader","_v$4","_v$5","seoPreviewTitle","_v$6","seoPreviewDesc","_v$7","seoPreviewUrl","removeProperty","a","o","i","n","s","SeoTab","reports","setReports","createSignal","analyzeHead","metaTags","Array","from","document","head","querySelectorAll","social","found","missing","tag","find","m","includes","getAttribute","push","useHeadChanges","_el$9","_tmpl$4","_el$0","_el$1","_el$10","_el$11","_el$12","_$createComponent","For","each","children","report","_el$13","_tmpl$5","_c$2","length","_el$14","_tmpl$6","_el$15","_el$16","_el$18","_el$19","_el$20","_tmpl$7","seoMissingTag","_v$14","seoMissingTagsSection","_v$15","seoMissingTagsList","_v$0","seoTabContainer","_v$1","seoTabSection","_v$10","sectionTitle","_v$11","sectionIcon","_v$12","sectionDescription","_v$13","seoPreviewSection"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import clsx from 'clsx'
|
|
2
|
+
import { DrawClientProvider } from '../context/draw-context'
|
|
2
3
|
import { useDevtoolsSettings, useHeight } from '../context/use-devtools-context'
|
|
3
4
|
import { useStyles } from '../styles/use-styles'
|
|
4
5
|
import { TANSTACK_DEVTOOLS } from '../utils/storage'
|
|
5
6
|
import { usePiPWindow } from '../context/pip-context'
|
|
7
|
+
|
|
6
8
|
import type { Accessor, JSX } from 'solid-js'
|
|
7
9
|
|
|
8
10
|
export const MainPanel = (props: {
|
|
@@ -30,7 +32,9 @@ export const MainPanel = (props: {
|
|
|
30
32
|
styles().devtoolsPanelContainerResizing(props.isResizing),
|
|
31
33
|
)}
|
|
32
34
|
>
|
|
33
|
-
{
|
|
35
|
+
<DrawClientProvider animationMs={400}>
|
|
36
|
+
{props.children}
|
|
37
|
+
</DrawClientProvider>
|
|
34
38
|
</div>
|
|
35
39
|
)
|
|
36
40
|
}
|
package/src/components/tabs.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import clsx from 'clsx'
|
|
|
2
2
|
import { For } from 'solid-js'
|
|
3
3
|
import { useStyles } from '../styles/use-styles'
|
|
4
4
|
import { useDevtoolsState } from '../context/use-devtools-context'
|
|
5
|
+
import { useDrawContext } from '../context/draw-context'
|
|
5
6
|
import { tabs } from '../tabs'
|
|
6
7
|
import { usePiPWindow } from '../context/pip-context'
|
|
7
8
|
|
|
@@ -18,6 +19,8 @@ export const Tabs = (props: TabsProps) => {
|
|
|
18
19
|
`width=${window.innerWidth},height=${state().height},top=${window.screen.height},left=${window.screenLeft}}`,
|
|
19
20
|
)
|
|
20
21
|
}
|
|
22
|
+
const { hoverUtils } = useDrawContext()
|
|
23
|
+
|
|
21
24
|
return (
|
|
22
25
|
<div class={styles().tabContainer}>
|
|
23
26
|
<For each={tabs}>
|
|
@@ -26,6 +29,12 @@ export const Tabs = (props: TabsProps) => {
|
|
|
26
29
|
type="button"
|
|
27
30
|
onClick={() => setState({ activeTab: tab.id })}
|
|
28
31
|
class={clsx(styles().tab, { active: state().activeTab === tab.id })}
|
|
32
|
+
onMouseEnter={() => {
|
|
33
|
+
if (tab.id === 'plugins') hoverUtils.enter()
|
|
34
|
+
}}
|
|
35
|
+
onMouseLeave={() => {
|
|
36
|
+
if (tab.id === 'plugins') hoverUtils.leave()
|
|
37
|
+
}}
|
|
29
38
|
>
|
|
30
39
|
{tab.icon}
|
|
31
40
|
</button>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createContext,
|
|
3
|
+
createMemo,
|
|
4
|
+
createSignal,
|
|
5
|
+
onCleanup,
|
|
6
|
+
useContext,
|
|
7
|
+
} from 'solid-js'
|
|
8
|
+
import type { ParentComponent } from 'solid-js'
|
|
9
|
+
|
|
10
|
+
const useDraw = (props: { animationMs: number }) => {
|
|
11
|
+
const [activeHover, setActiveHover] = createSignal<boolean>(false)
|
|
12
|
+
const [forceExpand, setForceExpand] = createSignal<boolean>(false)
|
|
13
|
+
|
|
14
|
+
const expanded = createMemo(() => activeHover() || forceExpand())
|
|
15
|
+
|
|
16
|
+
let hoverTimeout: ReturnType<typeof setTimeout> | null = null
|
|
17
|
+
onCleanup(() => {
|
|
18
|
+
if (hoverTimeout) clearTimeout(hoverTimeout)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const hoverUtils = {
|
|
22
|
+
enter: () => {
|
|
23
|
+
if (hoverTimeout) {
|
|
24
|
+
clearTimeout(hoverTimeout)
|
|
25
|
+
hoverTimeout = null
|
|
26
|
+
}
|
|
27
|
+
setActiveHover(true)
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
leave: () => {
|
|
31
|
+
hoverTimeout = setTimeout(() => {
|
|
32
|
+
setActiveHover(false)
|
|
33
|
+
}, props.animationMs)
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
expanded,
|
|
39
|
+
setForceExpand,
|
|
40
|
+
hoverUtils,
|
|
41
|
+
animationMs: props.animationMs,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type ContextType = ReturnType<typeof useDraw>
|
|
46
|
+
|
|
47
|
+
const DrawContext = createContext<ContextType | undefined>(undefined)
|
|
48
|
+
|
|
49
|
+
export const DrawClientProvider: ParentComponent<{
|
|
50
|
+
animationMs: number
|
|
51
|
+
}> = (props) => {
|
|
52
|
+
const value = useDraw({ animationMs: props.animationMs })
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<DrawContext.Provider value={value}>{props.children}</DrawContext.Provider>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function useDrawContext() {
|
|
60
|
+
const context = useContext(DrawContext)
|
|
61
|
+
|
|
62
|
+
if (context === undefined) {
|
|
63
|
+
throw new Error(`useDrawContext must be used within a DrawClientProvider`)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return context
|
|
67
|
+
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
onCleanup,
|
|
7
7
|
useContext,
|
|
8
8
|
} from 'solid-js'
|
|
9
|
-
import {
|
|
9
|
+
import { delegateEvents } from 'solid-js/web'
|
|
10
10
|
import type { Accessor, JSX } from 'solid-js'
|
|
11
11
|
|
|
12
12
|
interface PiPProviderProps {
|
|
@@ -69,8 +69,6 @@ export const PiPProvider = (props: PiPProviderProps) => {
|
|
|
69
69
|
pip.document.head.innerHTML = ''
|
|
70
70
|
// Remove existing body
|
|
71
71
|
pip.document.body.innerHTML = ''
|
|
72
|
-
// Clear Delegated Events
|
|
73
|
-
clearDelegatedEvents(pip.document)
|
|
74
72
|
|
|
75
73
|
pip.document.title = 'TanStack Devtools'
|
|
76
74
|
pip.document.body.style.margin = '0'
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { createMemo, useContext } from 'solid-js'
|
|
1
|
+
import { createEffect, createMemo, useContext } from 'solid-js'
|
|
2
2
|
import { DevtoolsContext } from './devtools-context.jsx'
|
|
3
|
-
|
|
3
|
+
import { useDrawContext } from './draw-context.jsx'
|
|
4
|
+
|
|
4
5
|
import type { DevtoolsStore } from './devtools-store.js'
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -19,10 +20,19 @@ const useDevtoolsContext = () => {
|
|
|
19
20
|
|
|
20
21
|
export const usePlugins = () => {
|
|
21
22
|
const { store, setStore } = useDevtoolsContext()
|
|
23
|
+
const { setForceExpand } = useDrawContext()
|
|
22
24
|
|
|
23
25
|
const plugins = createMemo(() => store.plugins)
|
|
24
26
|
const activePlugin = createMemo(() => store.state.activePlugin)
|
|
25
27
|
|
|
28
|
+
createEffect(() => {
|
|
29
|
+
if (activePlugin() == null) {
|
|
30
|
+
setForceExpand(false)
|
|
31
|
+
} else {
|
|
32
|
+
setForceExpand(true)
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
26
36
|
const setActivePlugin = (pluginId: string) => {
|
|
27
37
|
setStore((prev) => ({
|
|
28
38
|
...prev,
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { onCleanup, onMount } from 'solid-js'
|
|
2
|
+
|
|
3
|
+
type HeadChange =
|
|
4
|
+
| { kind: 'added'; node: Node }
|
|
5
|
+
| { kind: 'removed'; node: Node }
|
|
6
|
+
| {
|
|
7
|
+
kind: 'attr'
|
|
8
|
+
target: Element
|
|
9
|
+
name: string | null
|
|
10
|
+
oldValue: string | null
|
|
11
|
+
}
|
|
12
|
+
| { kind: 'title'; title: string }
|
|
13
|
+
|
|
14
|
+
type UseHeadChangesOptions = {
|
|
15
|
+
/**
|
|
16
|
+
* Observe attribute changes on elements inside <head>
|
|
17
|
+
* Default: true
|
|
18
|
+
*/
|
|
19
|
+
attributes?: boolean
|
|
20
|
+
/**
|
|
21
|
+
* Observe added/removed nodes in <head>
|
|
22
|
+
* Default: true
|
|
23
|
+
*/
|
|
24
|
+
childList?: boolean
|
|
25
|
+
/**
|
|
26
|
+
* Observe descendants of <head>
|
|
27
|
+
* Default: true
|
|
28
|
+
*/
|
|
29
|
+
subtree?: boolean
|
|
30
|
+
/**
|
|
31
|
+
* Also observe <title> changes explicitly
|
|
32
|
+
* Default: true
|
|
33
|
+
*/
|
|
34
|
+
observeTitle?: boolean
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function useHeadChanges(
|
|
38
|
+
onChange: (change: HeadChange, raw?: MutationRecord) => void,
|
|
39
|
+
opts: UseHeadChangesOptions = {},
|
|
40
|
+
) {
|
|
41
|
+
const {
|
|
42
|
+
attributes = true,
|
|
43
|
+
childList = true,
|
|
44
|
+
subtree = true,
|
|
45
|
+
observeTitle = true,
|
|
46
|
+
} = opts
|
|
47
|
+
|
|
48
|
+
onMount(() => {
|
|
49
|
+
const headObserver = new MutationObserver((mutations) => {
|
|
50
|
+
for (const m of mutations) {
|
|
51
|
+
if (m.type === 'childList') {
|
|
52
|
+
m.addedNodes.forEach((node) => onChange({ kind: 'added', node }, m))
|
|
53
|
+
m.removedNodes.forEach((node) =>
|
|
54
|
+
onChange({ kind: 'removed', node }, m),
|
|
55
|
+
)
|
|
56
|
+
} else if (m.type === 'attributes') {
|
|
57
|
+
const el = m.target as Element
|
|
58
|
+
onChange(
|
|
59
|
+
{
|
|
60
|
+
kind: 'attr',
|
|
61
|
+
target: el,
|
|
62
|
+
name: m.attributeName,
|
|
63
|
+
oldValue: m.oldValue ?? null,
|
|
64
|
+
},
|
|
65
|
+
m,
|
|
66
|
+
)
|
|
67
|
+
} else {
|
|
68
|
+
// If someone mutates a Text node inside <title>, surface it as a title change.
|
|
69
|
+
const isInTitle =
|
|
70
|
+
m.target.parentNode &&
|
|
71
|
+
(m.target.parentNode as Element).tagName.toLowerCase() === 'title'
|
|
72
|
+
if (isInTitle) onChange({ kind: 'title', title: document.title }, m)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
headObserver.observe(document.head, {
|
|
78
|
+
childList,
|
|
79
|
+
attributes,
|
|
80
|
+
subtree,
|
|
81
|
+
attributeOldValue: attributes,
|
|
82
|
+
characterData: true, // helps catch <title> text node edits
|
|
83
|
+
characterDataOldValue: false,
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
// Extra explicit observer for <title>, since `document.title = "..."`
|
|
87
|
+
// may not always bubble as a head mutation in all setups.
|
|
88
|
+
let titleObserver: MutationObserver | undefined
|
|
89
|
+
if (observeTitle) {
|
|
90
|
+
const titleEl =
|
|
91
|
+
document.head.querySelector('title') ||
|
|
92
|
+
// create a <title> if missing so future changes are observable
|
|
93
|
+
document.head.appendChild(document.createElement('title'))
|
|
94
|
+
|
|
95
|
+
titleObserver = new MutationObserver(() => {
|
|
96
|
+
onChange({ kind: 'title', title: document.title })
|
|
97
|
+
})
|
|
98
|
+
titleObserver.observe(titleEl, {
|
|
99
|
+
childList: true,
|
|
100
|
+
characterData: true,
|
|
101
|
+
subtree: true,
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
onCleanup(() => {
|
|
106
|
+
headObserver.disconnect()
|
|
107
|
+
titleObserver?.disconnect()
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
}
|