@sxl-studio/storybook-addon 1.0.13 → 1.0.15
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/index.d.ts +4 -0
- package/dist/index.js +69 -3
- package/dist/manager.js +84 -11
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -11,12 +11,17 @@ function fromDiffCodeConnect(data) {
|
|
|
11
11
|
const d = data;
|
|
12
12
|
const fileKey = typeof d.$figmaFileKey === "string" ? d.$figmaFileKey : "";
|
|
13
13
|
const fileName = typeof d.$figmaFileName === "string" ? d.$figmaFileName : void 0;
|
|
14
|
+
const repository = d.repository && typeof d.repository === "object" ? d.repository : void 0;
|
|
14
15
|
const isV2 = Array.isArray(d.components);
|
|
15
16
|
const entries = isV2 ? convertV2Components(d.components, fileKey) : convertV1Entries(Array.isArray(d.entries) ? d.entries : [], fileKey);
|
|
16
17
|
return {
|
|
17
18
|
version: 1,
|
|
18
19
|
figmaFileKey: fileKey,
|
|
19
20
|
figmaFileName: fileName,
|
|
21
|
+
repository: repository ? {
|
|
22
|
+
...typeof repository.url === "string" ? { url: repository.url } : {},
|
|
23
|
+
...typeof repository.documentationUrl === "string" ? { documentationUrl: repository.documentationUrl } : {}
|
|
24
|
+
} : void 0,
|
|
20
25
|
entries
|
|
21
26
|
};
|
|
22
27
|
}
|
|
@@ -29,7 +34,7 @@ function convertV2Components(components, fileKey) {
|
|
|
29
34
|
const nodeId = String(c.nodeId ?? "");
|
|
30
35
|
const sb = c.storybook ?? {};
|
|
31
36
|
const cc = c.codeConnect ?? {};
|
|
32
|
-
const figmaUrl = fileKey ? `https://www.figma.com/design/${fileKey}?node-id=${nodeId.replace(":", "-")}` : void 0;
|
|
37
|
+
const figmaUrl = typeof sb.figmaUrl === "string" && sb.figmaUrl.trim() ? sb.figmaUrl.trim() : fileKey ? `https://www.figma.com/design/${fileKey}?node-id=${nodeId.replace(":", "-")}` : void 0;
|
|
33
38
|
const statusRaw = typeof sb.status === "string" ? sb.status : void 0;
|
|
34
39
|
const readiness = statusRaw === "complete" || statusRaw === "ready-for-dev" || statusRaw === "in-progress" || statusRaw === "backlog" ? statusRaw : void 0;
|
|
35
40
|
const files = parseFiles(Array.isArray(cc.files) ? cc.files : []);
|
|
@@ -78,7 +83,7 @@ function convertV1Entries(rawEntries, fileKey) {
|
|
|
78
83
|
const b = e.binding;
|
|
79
84
|
const sb = b.storybook ?? {};
|
|
80
85
|
const nodeId = String(e.nodeId ?? "");
|
|
81
|
-
const figmaUrl = fileKey ? `https://www.figma.com/design/${fileKey}?node-id=${nodeId.replace(":", "-")}` : void 0;
|
|
86
|
+
const figmaUrl = typeof sb.figmaUrl === "string" && sb.figmaUrl.trim() ? sb.figmaUrl.trim() : fileKey ? `https://www.figma.com/design/${fileKey}?node-id=${nodeId.replace(":", "-")}` : void 0;
|
|
82
87
|
const statusRaw = typeof sb.status === "string" ? sb.status : void 0;
|
|
83
88
|
const readiness = statusRaw === "complete" || statusRaw === "ready-for-dev" || statusRaw === "in-progress" || statusRaw === "backlog" ? statusRaw : void 0;
|
|
84
89
|
const files = parseFiles(Array.isArray(b.files) ? b.files : []);
|
|
@@ -133,6 +138,54 @@ function joinFetchUrl(base, path) {
|
|
|
133
138
|
const segments = normalizeCompositionPath(path).split("/").filter(Boolean);
|
|
134
139
|
return b + segments.map(encodeURIComponent).join("/");
|
|
135
140
|
}
|
|
141
|
+
function candidateRelativePaths(path) {
|
|
142
|
+
const n = normalizeCompositionPath(path);
|
|
143
|
+
const out = [n];
|
|
144
|
+
if (n.startsWith("components/")) {
|
|
145
|
+
out.push(n.slice("components/".length));
|
|
146
|
+
}
|
|
147
|
+
return Array.from(new Set(out));
|
|
148
|
+
}
|
|
149
|
+
function buildGitlabRawCandidates(repositoryUrl, path) {
|
|
150
|
+
let parsed;
|
|
151
|
+
try {
|
|
152
|
+
parsed = new URL(repositoryUrl);
|
|
153
|
+
} catch {
|
|
154
|
+
return [];
|
|
155
|
+
}
|
|
156
|
+
const cleanPath = parsed.pathname.replace(/\/+$/, "");
|
|
157
|
+
const marker = "/-/tree/";
|
|
158
|
+
const idx = cleanPath.indexOf(marker);
|
|
159
|
+
if (idx < 0) return [];
|
|
160
|
+
const prefix = cleanPath.slice(0, idx);
|
|
161
|
+
const tail = cleanPath.slice(idx + marker.length);
|
|
162
|
+
const slash = tail.indexOf("/");
|
|
163
|
+
const ref = slash >= 0 ? tail.slice(0, slash) : tail;
|
|
164
|
+
const baseDir = slash >= 0 ? tail.slice(slash + 1) : "";
|
|
165
|
+
const baseRaw = `${parsed.origin}${prefix}/-/raw/${encodeURIComponent(ref)}` + (baseDir ? `/${baseDir.split("/").map(encodeURIComponent).join("/")}` : "");
|
|
166
|
+
return candidateRelativePaths(path).map((rel) => joinFetchUrl(baseRaw, rel));
|
|
167
|
+
}
|
|
168
|
+
function extractRepositoryUrl(params) {
|
|
169
|
+
const raw = params?.registry;
|
|
170
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
171
|
+
const repo = raw.repository;
|
|
172
|
+
if (!repo || typeof repo !== "object") return void 0;
|
|
173
|
+
const url = repo.url;
|
|
174
|
+
return typeof url === "string" && url.trim() ? url.trim() : void 0;
|
|
175
|
+
}
|
|
176
|
+
async function fetchFirstOk(urls) {
|
|
177
|
+
for (const url of urls) {
|
|
178
|
+
try {
|
|
179
|
+
const res = await fetch(url, { credentials: "include" });
|
|
180
|
+
if (!res.ok) continue;
|
|
181
|
+
const text = await res.text();
|
|
182
|
+
if (!text.trim()) continue;
|
|
183
|
+
return { text, url };
|
|
184
|
+
} catch {
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
136
189
|
async function loadCompositionJsonText(path, legacyInline, params) {
|
|
137
190
|
const inline = legacyInline?.trim();
|
|
138
191
|
if (inline) {
|
|
@@ -176,8 +229,21 @@ async function loadCompositionJsonText(path, legacyInline, params) {
|
|
|
176
229
|
return { error: `Fetch failed: ${msg}` };
|
|
177
230
|
}
|
|
178
231
|
}
|
|
232
|
+
const repoUrl = extractRepositoryUrl(params);
|
|
233
|
+
if (repoUrl) {
|
|
234
|
+
const gitlabCandidates = buildGitlabRawCandidates(repoUrl, p);
|
|
235
|
+
const hit = await fetchFirstOk(gitlabCandidates);
|
|
236
|
+
if (hit) {
|
|
237
|
+
return { text: hit.text, source: "fetch" };
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
const localCandidates = candidateRelativePaths(p).map((rel) => `/${rel}`);
|
|
241
|
+
const localHit = await fetchFirstOk(localCandidates);
|
|
242
|
+
if (localHit) {
|
|
243
|
+
return { text: localHit.text, source: "fetch" };
|
|
244
|
+
}
|
|
179
245
|
return {
|
|
180
|
-
error: "Composition file is not inlined. Pass parameters.sxl.compositionSources, compositionFetchBaseUrl + staticDirs, or resolveComposition() in preview \u2014 see @sxl-studio/storybook-addon README."
|
|
246
|
+
error: "Composition file is not inlined and auto-fetch failed. Pass parameters.sxl.compositionSources, compositionFetchBaseUrl + staticDirs, or resolveComposition() in preview \u2014 see @sxl-studio/storybook-addon README."
|
|
181
247
|
};
|
|
182
248
|
}
|
|
183
249
|
export {
|
package/dist/manager.js
CHANGED
|
@@ -19,12 +19,17 @@ function fromDiffCodeConnect(data) {
|
|
|
19
19
|
const d = data;
|
|
20
20
|
const fileKey = typeof d.$figmaFileKey === "string" ? d.$figmaFileKey : "";
|
|
21
21
|
const fileName = typeof d.$figmaFileName === "string" ? d.$figmaFileName : void 0;
|
|
22
|
+
const repository = d.repository && typeof d.repository === "object" ? d.repository : void 0;
|
|
22
23
|
const isV2 = Array.isArray(d.components);
|
|
23
24
|
const entries = isV2 ? convertV2Components(d.components, fileKey) : convertV1Entries(Array.isArray(d.entries) ? d.entries : [], fileKey);
|
|
24
25
|
return {
|
|
25
26
|
version: 1,
|
|
26
27
|
figmaFileKey: fileKey,
|
|
27
28
|
figmaFileName: fileName,
|
|
29
|
+
repository: repository ? {
|
|
30
|
+
...typeof repository.url === "string" ? { url: repository.url } : {},
|
|
31
|
+
...typeof repository.documentationUrl === "string" ? { documentationUrl: repository.documentationUrl } : {}
|
|
32
|
+
} : void 0,
|
|
28
33
|
entries
|
|
29
34
|
};
|
|
30
35
|
}
|
|
@@ -37,7 +42,7 @@ function convertV2Components(components, fileKey) {
|
|
|
37
42
|
const nodeId = String(c.nodeId ?? "");
|
|
38
43
|
const sb = c.storybook ?? {};
|
|
39
44
|
const cc = c.codeConnect ?? {};
|
|
40
|
-
const figmaUrl = fileKey ? `https://www.figma.com/design/${fileKey}?node-id=${nodeId.replace(":", "-")}` : void 0;
|
|
45
|
+
const figmaUrl = typeof sb.figmaUrl === "string" && sb.figmaUrl.trim() ? sb.figmaUrl.trim() : fileKey ? `https://www.figma.com/design/${fileKey}?node-id=${nodeId.replace(":", "-")}` : void 0;
|
|
41
46
|
const statusRaw = typeof sb.status === "string" ? sb.status : void 0;
|
|
42
47
|
const readiness = statusRaw === "complete" || statusRaw === "ready-for-dev" || statusRaw === "in-progress" || statusRaw === "backlog" ? statusRaw : void 0;
|
|
43
48
|
const files = parseFiles(Array.isArray(cc.files) ? cc.files : []);
|
|
@@ -86,7 +91,7 @@ function convertV1Entries(rawEntries, fileKey) {
|
|
|
86
91
|
const b = e.binding;
|
|
87
92
|
const sb = b.storybook ?? {};
|
|
88
93
|
const nodeId = String(e.nodeId ?? "");
|
|
89
|
-
const figmaUrl = fileKey ? `https://www.figma.com/design/${fileKey}?node-id=${nodeId.replace(":", "-")}` : void 0;
|
|
94
|
+
const figmaUrl = typeof sb.figmaUrl === "string" && sb.figmaUrl.trim() ? sb.figmaUrl.trim() : fileKey ? `https://www.figma.com/design/${fileKey}?node-id=${nodeId.replace(":", "-")}` : void 0;
|
|
90
95
|
const statusRaw = typeof sb.status === "string" ? sb.status : void 0;
|
|
91
96
|
const readiness = statusRaw === "complete" || statusRaw === "ready-for-dev" || statusRaw === "in-progress" || statusRaw === "backlog" ? statusRaw : void 0;
|
|
92
97
|
const files = parseFiles(Array.isArray(b.files) ? b.files : []);
|
|
@@ -141,6 +146,54 @@ function joinFetchUrl(base, path) {
|
|
|
141
146
|
const segments = normalizeCompositionPath(path).split("/").filter(Boolean);
|
|
142
147
|
return b + segments.map(encodeURIComponent).join("/");
|
|
143
148
|
}
|
|
149
|
+
function candidateRelativePaths(path) {
|
|
150
|
+
const n = normalizeCompositionPath(path);
|
|
151
|
+
const out = [n];
|
|
152
|
+
if (n.startsWith("components/")) {
|
|
153
|
+
out.push(n.slice("components/".length));
|
|
154
|
+
}
|
|
155
|
+
return Array.from(new Set(out));
|
|
156
|
+
}
|
|
157
|
+
function buildGitlabRawCandidates(repositoryUrl, path) {
|
|
158
|
+
let parsed;
|
|
159
|
+
try {
|
|
160
|
+
parsed = new URL(repositoryUrl);
|
|
161
|
+
} catch {
|
|
162
|
+
return [];
|
|
163
|
+
}
|
|
164
|
+
const cleanPath = parsed.pathname.replace(/\/+$/, "");
|
|
165
|
+
const marker = "/-/tree/";
|
|
166
|
+
const idx = cleanPath.indexOf(marker);
|
|
167
|
+
if (idx < 0) return [];
|
|
168
|
+
const prefix = cleanPath.slice(0, idx);
|
|
169
|
+
const tail = cleanPath.slice(idx + marker.length);
|
|
170
|
+
const slash = tail.indexOf("/");
|
|
171
|
+
const ref = slash >= 0 ? tail.slice(0, slash) : tail;
|
|
172
|
+
const baseDir = slash >= 0 ? tail.slice(slash + 1) : "";
|
|
173
|
+
const baseRaw = `${parsed.origin}${prefix}/-/raw/${encodeURIComponent(ref)}` + (baseDir ? `/${baseDir.split("/").map(encodeURIComponent).join("/")}` : "");
|
|
174
|
+
return candidateRelativePaths(path).map((rel) => joinFetchUrl(baseRaw, rel));
|
|
175
|
+
}
|
|
176
|
+
function extractRepositoryUrl(params) {
|
|
177
|
+
const raw = params?.registry;
|
|
178
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
179
|
+
const repo = raw.repository;
|
|
180
|
+
if (!repo || typeof repo !== "object") return void 0;
|
|
181
|
+
const url = repo.url;
|
|
182
|
+
return typeof url === "string" && url.trim() ? url.trim() : void 0;
|
|
183
|
+
}
|
|
184
|
+
async function fetchFirstOk(urls) {
|
|
185
|
+
for (const url of urls) {
|
|
186
|
+
try {
|
|
187
|
+
const res = await fetch(url, { credentials: "include" });
|
|
188
|
+
if (!res.ok) continue;
|
|
189
|
+
const text = await res.text();
|
|
190
|
+
if (!text.trim()) continue;
|
|
191
|
+
return { text, url };
|
|
192
|
+
} catch {
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
144
197
|
async function loadCompositionJsonText(path, legacyInline, params) {
|
|
145
198
|
const inline = legacyInline?.trim();
|
|
146
199
|
if (inline) {
|
|
@@ -184,8 +237,21 @@ async function loadCompositionJsonText(path, legacyInline, params) {
|
|
|
184
237
|
return { error: `Fetch failed: ${msg}` };
|
|
185
238
|
}
|
|
186
239
|
}
|
|
240
|
+
const repoUrl = extractRepositoryUrl(params);
|
|
241
|
+
if (repoUrl) {
|
|
242
|
+
const gitlabCandidates = buildGitlabRawCandidates(repoUrl, p);
|
|
243
|
+
const hit = await fetchFirstOk(gitlabCandidates);
|
|
244
|
+
if (hit) {
|
|
245
|
+
return { text: hit.text, source: "fetch" };
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const localCandidates = candidateRelativePaths(p).map((rel) => `/${rel}`);
|
|
249
|
+
const localHit = await fetchFirstOk(localCandidates);
|
|
250
|
+
if (localHit) {
|
|
251
|
+
return { text: localHit.text, source: "fetch" };
|
|
252
|
+
}
|
|
187
253
|
return {
|
|
188
|
-
error: "Composition file is not inlined. Pass parameters.sxl.compositionSources, compositionFetchBaseUrl + staticDirs, or resolveComposition() in preview \u2014 see @sxl-studio/storybook-addon README."
|
|
254
|
+
error: "Composition file is not inlined and auto-fetch failed. Pass parameters.sxl.compositionSources, compositionFetchBaseUrl + staticDirs, or resolveComposition() in preview \u2014 see @sxl-studio/storybook-addon README."
|
|
189
255
|
};
|
|
190
256
|
}
|
|
191
257
|
|
|
@@ -3823,16 +3889,25 @@ var SxlPanel = () => {
|
|
|
3823
3889
|
}, []);
|
|
3824
3890
|
const entryForRender = result.status === "found" ? result.entry : null;
|
|
3825
3891
|
const showEmbed = !!entryForRender?.figmaUrl && entryForRender.designEmbed !== false;
|
|
3892
|
+
const renderEmbedSection = entryForRender?.designEmbed === true || !!entryForRender?.figmaUrl;
|
|
3826
3893
|
useEffect(() => {
|
|
3827
|
-
if (!
|
|
3894
|
+
if (!entryForRender) return;
|
|
3895
|
+
if (entryForRender.designEmbed === true && !entryForRender.figmaUrl) {
|
|
3896
|
+
console.warn(
|
|
3897
|
+
"[SXL Studio addon] Embed requested but figmaUrl is missing. Check diff `$figmaFileKey` or set `storybook.figmaUrl` in entry.",
|
|
3898
|
+
{ nodeId: entryForRender.nodeId, displayName: entryForRender.displayName }
|
|
3899
|
+
);
|
|
3900
|
+
return;
|
|
3901
|
+
}
|
|
3902
|
+
if (!showEmbed || !entryForRender.figmaUrl) return;
|
|
3828
3903
|
const embedUrl = buildEmbedUrl(entryForRender.figmaUrl);
|
|
3829
3904
|
console.info("[SXL Studio addon] Figma embed", {
|
|
3830
3905
|
designEmbed: entryForRender.designEmbed,
|
|
3831
3906
|
figmaUrl: entryForRender.figmaUrl,
|
|
3832
3907
|
embedUrl,
|
|
3833
|
-
hint: "If
|
|
3908
|
+
hint: "If iframe is blank, verify Storybook CSP frame-src includes https://www.figma.com"
|
|
3834
3909
|
});
|
|
3835
|
-
}, [
|
|
3910
|
+
}, [showEmbed, entryForRender?.figmaUrl, entryForRender?.designEmbed, entryForRender?.nodeId, entryForRender?.displayName]);
|
|
3836
3911
|
if (result.status === "no-registry") {
|
|
3837
3912
|
return React2.createElement(NoRegistryState, null);
|
|
3838
3913
|
}
|
|
@@ -3846,7 +3921,7 @@ var SxlPanel = () => {
|
|
|
3846
3921
|
const readiness = entry.meta?.readiness;
|
|
3847
3922
|
const dateStr = formatDate(entry.updatedAt);
|
|
3848
3923
|
const apiProps = entry.componentApi?.properties;
|
|
3849
|
-
return /* @__PURE__ */ React2.createElement("div", { style: panelRoot }, /* @__PURE__ */ React2.createElement("div", { style: topRow }, /* @__PURE__ */ React2.createElement("div", { style: titleBlock }, entry.displayName ? /* @__PURE__ */ React2.createElement("h2", { style: componentName }, entry.displayName) : null), /* @__PURE__ */ React2.createElement("div", { style: metaCol }, dateStr ? /* @__PURE__ */ React2.createElement("div", { style: dateText }, "Updated ", dateStr) : null, /* @__PURE__ */ React2.createElement("div", { style: badgeRow }, /* @__PURE__ */ React2.createElement(TokensBadge, { value: tokensBool }), readiness ? /* @__PURE__ */ React2.createElement(ReadinessBadge, { readiness }) : null))), entry.description ? /* @__PURE__ */ React2.createElement("div", { style: section }, /* @__PURE__ */ React2.createElement("div", { style: sectionLabel }, "Description"), /* @__PURE__ */ React2.createElement("div", { style: card }, /* @__PURE__ */ React2.createElement("p", { style: descriptionText }, entry.description))) : null,
|
|
3924
|
+
return /* @__PURE__ */ React2.createElement("div", { style: panelRoot }, /* @__PURE__ */ React2.createElement("div", { style: topRow }, /* @__PURE__ */ React2.createElement("div", { style: titleBlock }, entry.displayName ? /* @__PURE__ */ React2.createElement("h2", { style: componentName }, entry.displayName) : null), /* @__PURE__ */ React2.createElement("div", { style: metaCol }, dateStr ? /* @__PURE__ */ React2.createElement("div", { style: dateText }, "Updated ", dateStr) : null, /* @__PURE__ */ React2.createElement("div", { style: badgeRow }, /* @__PURE__ */ React2.createElement(TokensBadge, { value: tokensBool }), readiness ? /* @__PURE__ */ React2.createElement(ReadinessBadge, { readiness }) : null))), entry.description ? /* @__PURE__ */ React2.createElement("div", { style: section }, /* @__PURE__ */ React2.createElement("div", { style: sectionLabel }, "Description"), /* @__PURE__ */ React2.createElement("div", { style: card }, /* @__PURE__ */ React2.createElement("p", { style: descriptionText }, entry.description))) : null, renderEmbedSection ? /* @__PURE__ */ React2.createElement("div", { style: section }, /* @__PURE__ */ React2.createElement("div", { style: sectionLabel }, "Embed"), showEmbed ? /* @__PURE__ */ React2.createElement("div", { style: embedWrap }, /* @__PURE__ */ React2.createElement(
|
|
3850
3925
|
"iframe",
|
|
3851
3926
|
{
|
|
3852
3927
|
title: "Figma embed",
|
|
@@ -3856,9 +3931,7 @@ var SxlPanel = () => {
|
|
|
3856
3931
|
allow: "clipboard-write; fullscreen",
|
|
3857
3932
|
referrerPolicy: "no-referrer-when-downgrade",
|
|
3858
3933
|
onLoad: () => {
|
|
3859
|
-
|
|
3860
|
-
console.info("[SXL Studio addon] Figma iframe load event fired");
|
|
3861
|
-
}
|
|
3934
|
+
console.info("[SXL Studio addon] Figma iframe load event fired");
|
|
3862
3935
|
}
|
|
3863
3936
|
}
|
|
3864
3937
|
), /* @__PURE__ */ React2.createElement("div", { style: embedFooter }, /* @__PURE__ */ React2.createElement(
|
|
@@ -3879,7 +3952,7 @@ var SxlPanel = () => {
|
|
|
3879
3952
|
style: link
|
|
3880
3953
|
},
|
|
3881
3954
|
"Open in Figma Dev Mode \u2192"
|
|
3882
|
-
)))) : entry.figmaUrl ? /* @__PURE__ */ React2.createElement("div", { style: section }, /* @__PURE__ */ React2.createElement(
|
|
3955
|
+
))) : /* @__PURE__ */ React2.createElement("div", { style: card }, /* @__PURE__ */ React2.createElement("p", { style: { ...descriptionText, margin: 0 } }, "Embed is enabled but Figma URL is missing in registry entry. Re-link this component in plugin or ensure `diff-code-connect` has `$figmaFileKey` (or `storybook.figmaUrl`)."), /* @__PURE__ */ React2.createElement("p", { style: { ...descriptionText, margin: "8px 0 0", fontSize: "12px" } }, "Node: ", /* @__PURE__ */ React2.createElement("code", { style: emptyCode }, entry.nodeId)))) : entry.figmaUrl ? /* @__PURE__ */ React2.createElement("div", { style: section }, /* @__PURE__ */ React2.createElement(
|
|
3883
3956
|
"a",
|
|
3884
3957
|
{
|
|
3885
3958
|
href: buildDevModeUrl(entry.figmaUrl),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sxl-studio/storybook-addon",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"description": "Storybook addon for SXL Studio — displays Figma Embed, component info and design token status for linked components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|