@storybook/addon-onboarding 10.1.0-alpha.12 → 10.1.0-alpha.14
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/_browser-chunks/{Onboarding-WWQZBI4C.js → Onboarding-4UKVZPT6.js} +346 -461
- package/dist/_browser-chunks/Survey-RTIK67MQ.js +35 -0
- package/dist/_browser-chunks/chunk-BTSM33XX.js +181 -0
- package/dist/_browser-chunks/chunk-VFOIHBP2.js +8 -0
- package/dist/manager.js +24 -22
- package/dist/preset.js +9 -9
- package/package.json +2 -2
- package/dist/_browser-chunks/chunk-BG2SBT4L.js +0 -7
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IntentSurvey
|
|
3
|
+
} from "./chunk-BTSM33XX.js";
|
|
4
|
+
import {
|
|
5
|
+
ADDON_ONBOARDING_CHANNEL
|
|
6
|
+
} from "./chunk-VFOIHBP2.js";
|
|
7
|
+
import "./chunk-ZYVL3X5E.js";
|
|
8
|
+
|
|
9
|
+
// src/Survey.tsx
|
|
10
|
+
import React, { useCallback } from "react";
|
|
11
|
+
import { ThemeProvider, convert } from "storybook/theming";
|
|
12
|
+
var theme = convert();
|
|
13
|
+
function Survey({ api }) {
|
|
14
|
+
let userAgent = globalThis?.navigator?.userAgent, disableOnboarding = useCallback(() => {
|
|
15
|
+
let url = new URL(window.location.href);
|
|
16
|
+
url.searchParams.set("onboarding", "false"), history.replaceState({}, "", url.href), api.setQueryParams({ onboarding: "false" });
|
|
17
|
+
}, [api]), complete = useCallback(
|
|
18
|
+
(answers) => {
|
|
19
|
+
api.emit(ADDON_ONBOARDING_CHANNEL, {
|
|
20
|
+
answers,
|
|
21
|
+
type: "survey",
|
|
22
|
+
userAgent
|
|
23
|
+
}), disableOnboarding();
|
|
24
|
+
},
|
|
25
|
+
[api, disableOnboarding, userAgent]
|
|
26
|
+
), dismiss = useCallback(() => {
|
|
27
|
+
api.emit(ADDON_ONBOARDING_CHANNEL, {
|
|
28
|
+
type: "dismissSurvey"
|
|
29
|
+
}), disableOnboarding();
|
|
30
|
+
}, [api, disableOnboarding]);
|
|
31
|
+
return React.createElement(ThemeProvider, { theme }, React.createElement(IntentSurvey, { onComplete: complete, onDismiss: dismiss }));
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
Survey as default
|
|
35
|
+
};
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
// src/features/IntentSurvey/IntentSurvey.tsx
|
|
2
|
+
import React, { Fragment, useState } from "react";
|
|
3
|
+
import { Button, Form, Modal } from "storybook/internal/components";
|
|
4
|
+
import { styled } from "storybook/theming";
|
|
5
|
+
|
|
6
|
+
// ../../.storybook/isChromatic.ts
|
|
7
|
+
function isChromatic(windowArg) {
|
|
8
|
+
let windowToCheck = windowArg || typeof window < "u" && window;
|
|
9
|
+
return !!(windowToCheck && (windowToCheck.navigator.userAgent.match(/Chromatic/) || windowToCheck.location.href.match(/chromatic=true/)));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// src/features/IntentSurvey/IntentSurvey.tsx
|
|
13
|
+
var Content = styled(Modal.Content)(({ theme }) => ({
|
|
14
|
+
fontSize: theme.typography.size.s2,
|
|
15
|
+
color: theme.color.defaultText,
|
|
16
|
+
gap: 8
|
|
17
|
+
})), Row = styled.div({
|
|
18
|
+
display: "grid",
|
|
19
|
+
gridTemplateColumns: "1fr 1fr",
|
|
20
|
+
gap: 14,
|
|
21
|
+
marginBottom: 8
|
|
22
|
+
}), Question = styled.div(({ theme }) => ({
|
|
23
|
+
marginTop: 8,
|
|
24
|
+
marginBottom: 2,
|
|
25
|
+
fontWeight: theme.typography.weight.bold
|
|
26
|
+
})), Label = styled.label({
|
|
27
|
+
display: "flex",
|
|
28
|
+
gap: 8,
|
|
29
|
+
'&:has(input[type="checkbox"]:not(:disabled), input[type="radio"]:not(:disabled))': {
|
|
30
|
+
cursor: "pointer"
|
|
31
|
+
}
|
|
32
|
+
}), Actions = styled(Modal.Actions)({
|
|
33
|
+
marginTop: 8
|
|
34
|
+
}), Checkbox = styled(Form.Checkbox)({
|
|
35
|
+
margin: 2
|
|
36
|
+
}), IntentSurvey = ({
|
|
37
|
+
onComplete,
|
|
38
|
+
onDismiss
|
|
39
|
+
}) => {
|
|
40
|
+
let [isSubmitting, setIsSubmitting] = useState(!1), [formFields, setFormFields] = useState({
|
|
41
|
+
building: {
|
|
42
|
+
label: "What are you building?",
|
|
43
|
+
type: "checkbox",
|
|
44
|
+
required: !0,
|
|
45
|
+
options: shuffleObject({
|
|
46
|
+
"design-system": { label: "Design system" },
|
|
47
|
+
"application-ui": { label: "Application UI" }
|
|
48
|
+
}),
|
|
49
|
+
values: {
|
|
50
|
+
"design-system": !1,
|
|
51
|
+
"application-ui": !1
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
interest: {
|
|
55
|
+
label: "Which of these are you interested in?",
|
|
56
|
+
type: "checkbox",
|
|
57
|
+
required: !0,
|
|
58
|
+
options: shuffleObject({
|
|
59
|
+
"ui-documentation": { label: "Generating UI docs" },
|
|
60
|
+
"functional-testing": { label: "Functional testing" },
|
|
61
|
+
"accessibility-testing": { label: "Accessibility testing" },
|
|
62
|
+
"visual-testing": { label: "Visual testing" },
|
|
63
|
+
"ai-augmented-development": { label: "Building UI with AI" },
|
|
64
|
+
"team-collaboration": { label: "Team collaboration" },
|
|
65
|
+
"design-handoff": { label: "Design handoff" }
|
|
66
|
+
}),
|
|
67
|
+
values: {
|
|
68
|
+
"ui-documentation": !1,
|
|
69
|
+
"functional-testing": !1,
|
|
70
|
+
"accessibility-testing": !1,
|
|
71
|
+
"visual-testing": !1,
|
|
72
|
+
"ai-augmented-development": !1,
|
|
73
|
+
"team-collaboration": !1,
|
|
74
|
+
"design-handoff": !1
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
referrer: {
|
|
78
|
+
label: "How did you discover Storybook?",
|
|
79
|
+
type: "select",
|
|
80
|
+
required: !0,
|
|
81
|
+
options: shuffleObject({
|
|
82
|
+
"we-use-it-at-work": { label: "We use it at work" },
|
|
83
|
+
"via-friend-or-colleague": { label: "Via friend or colleague" },
|
|
84
|
+
"via-social-media": { label: "Via social media" },
|
|
85
|
+
youtube: { label: "YouTube" },
|
|
86
|
+
"web-search": { label: "Web Search" },
|
|
87
|
+
"ai-agent": { label: "AI Agent (e.g. ChatGPT)" }
|
|
88
|
+
}),
|
|
89
|
+
values: {
|
|
90
|
+
"we-use-it-at-work": !1,
|
|
91
|
+
"via-friend-or-colleague": !1,
|
|
92
|
+
"via-social-media": !1,
|
|
93
|
+
youtube: !1,
|
|
94
|
+
"web-search": !1,
|
|
95
|
+
"ai-agent": !1
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}), updateFormData = (key, optionOrValue, value) => {
|
|
99
|
+
let field = formFields[key];
|
|
100
|
+
setFormFields((fields) => {
|
|
101
|
+
if (field.type === "checkbox") {
|
|
102
|
+
let values = { ...field.values, [optionOrValue]: !!value };
|
|
103
|
+
return { ...fields, [key]: { ...field, values } };
|
|
104
|
+
}
|
|
105
|
+
if (field.type === "select") {
|
|
106
|
+
let values = Object.fromEntries(
|
|
107
|
+
Object.entries(field.values).map(([opt]) => [opt, opt === optionOrValue])
|
|
108
|
+
);
|
|
109
|
+
return { ...fields, [key]: { ...field, values } };
|
|
110
|
+
}
|
|
111
|
+
return fields;
|
|
112
|
+
});
|
|
113
|
+
}, isValid = Object.values(formFields).every((field) => field.required ? Object.values(field.values).some((value) => value === !0) : !0);
|
|
114
|
+
return React.createElement(
|
|
115
|
+
Modal,
|
|
116
|
+
{
|
|
117
|
+
ariaLabel: "Storybook user survey",
|
|
118
|
+
defaultOpen: !0,
|
|
119
|
+
width: 420,
|
|
120
|
+
onOpenChange: (isOpen) => {
|
|
121
|
+
isOpen || onDismiss();
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
React.createElement(Form, { onSubmit: (e) => {
|
|
125
|
+
isValid && (e.preventDefault(), setIsSubmitting(!0), onComplete(
|
|
126
|
+
Object.fromEntries(Object.entries(formFields).map(([key, field]) => [key, field.values]))
|
|
127
|
+
));
|
|
128
|
+
}, id: "intent-survey-form" }, React.createElement(Content, null, React.createElement(Modal.Header, { onClose: onDismiss }, React.createElement(Modal.Title, null, "Help improve Storybook")), Object.keys(formFields).map((key) => {
|
|
129
|
+
let field = formFields[key];
|
|
130
|
+
return React.createElement(Fragment, { key }, React.createElement(Question, null, field.label), field.type === "checkbox" && React.createElement(Row, null, Object.entries(field.options).map(([opt, option]) => {
|
|
131
|
+
let id = `${key}:${opt}`;
|
|
132
|
+
return React.createElement("div", { key: id }, React.createElement(Label, { htmlFor: id }, React.createElement(
|
|
133
|
+
Checkbox,
|
|
134
|
+
{
|
|
135
|
+
name: id,
|
|
136
|
+
id,
|
|
137
|
+
checked: field.values[opt],
|
|
138
|
+
disabled: isSubmitting,
|
|
139
|
+
onChange: (e) => updateFormData(key, opt, e.target.checked)
|
|
140
|
+
}
|
|
141
|
+
), option.label));
|
|
142
|
+
})), field.type === "select" && React.createElement(
|
|
143
|
+
Form.Select,
|
|
144
|
+
{
|
|
145
|
+
name: key,
|
|
146
|
+
id: key,
|
|
147
|
+
value: Object.entries(field.values).find(([, isSelected]) => isSelected)?.[0] || "",
|
|
148
|
+
required: field.required,
|
|
149
|
+
disabled: isSubmitting,
|
|
150
|
+
onChange: (e) => updateFormData(key, e.target.value)
|
|
151
|
+
},
|
|
152
|
+
React.createElement("option", { disabled: !0, hidden: !0, value: "" }, "Select an option..."),
|
|
153
|
+
Object.entries(field.options).map(([opt, option]) => React.createElement("option", { key: opt, value: opt }, option.label))
|
|
154
|
+
));
|
|
155
|
+
}), React.createElement(Actions, null, React.createElement(
|
|
156
|
+
Button,
|
|
157
|
+
{
|
|
158
|
+
ariaLabel: !1,
|
|
159
|
+
disabled: isSubmitting || !isValid,
|
|
160
|
+
size: "medium",
|
|
161
|
+
type: "submit",
|
|
162
|
+
variant: "solid"
|
|
163
|
+
},
|
|
164
|
+
"Submit"
|
|
165
|
+
))))
|
|
166
|
+
);
|
|
167
|
+
};
|
|
168
|
+
function shuffle(array) {
|
|
169
|
+
for (let i = array.length - 1; i > 0; i--) {
|
|
170
|
+
let j = Math.floor(Math.random() * (i + 1));
|
|
171
|
+
[array[i], array[j]] = [array[j], array[i]];
|
|
172
|
+
}
|
|
173
|
+
return array;
|
|
174
|
+
}
|
|
175
|
+
function shuffleObject(object) {
|
|
176
|
+
return isChromatic() ? object : Object.fromEntries(shuffle(Object.entries(object)));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export {
|
|
180
|
+
IntentSurvey
|
|
181
|
+
};
|
package/dist/manager.js
CHANGED
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ADDON_CONTROLS_ID
|
|
3
|
-
|
|
2
|
+
ADDON_CONTROLS_ID,
|
|
3
|
+
ADDON_ID
|
|
4
|
+
} from "./_browser-chunks/chunk-VFOIHBP2.js";
|
|
4
5
|
import "./_browser-chunks/chunk-ZYVL3X5E.js";
|
|
5
6
|
|
|
6
7
|
// src/manager.tsx
|
|
7
8
|
import React, { Suspense, lazy } from "react";
|
|
8
|
-
import
|
|
9
|
+
import { createRoot } from "react-dom/client";
|
|
9
10
|
import { STORY_SPECIFIED } from "storybook/internal/core-events";
|
|
10
|
-
import { addons } from "storybook/manager-api";
|
|
11
|
-
var Onboarding = lazy(() => import("./_browser-chunks/Onboarding-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
if (!isOnboarding || window.innerWidth < 730)
|
|
22
|
-
return;
|
|
23
|
-
api.togglePanel(!0), api.togglePanelPosition("bottom"), api.setSelectedPanel(ADDON_CONTROLS_ID);
|
|
24
|
-
let domNode = document.createElement("div");
|
|
25
|
-
domNode.id = "storybook-addon-onboarding", document.body.appendChild(domNode), ReactDOM.render(
|
|
26
|
-
React.createElement(Suspense, { fallback: React.createElement("div", null) }, React.createElement(Onboarding, { api })),
|
|
27
|
-
domNode
|
|
28
|
-
);
|
|
11
|
+
import { addons, internal_universalChecklistStore as checklistStore } from "storybook/manager-api";
|
|
12
|
+
var Onboarding = lazy(() => import("./_browser-chunks/Onboarding-4UKVZPT6.js")), Survey = lazy(() => import("./_browser-chunks/Survey-RTIK67MQ.js")), root = null, render = (node) => {
|
|
13
|
+
let container = document.getElementById("storybook-addon-onboarding");
|
|
14
|
+
container || (container = document.createElement("div"), container.id = "storybook-addon-onboarding", document.body.appendChild(container)), root = root ?? createRoot(container), root.render(React.createElement(Suspense, { fallback: React.createElement("div", null) }, node));
|
|
15
|
+
};
|
|
16
|
+
addons.register(ADDON_ID, async (api) => {
|
|
17
|
+
let { path, queryParams } = api.getUrlState(), isOnboarding = path === "/onboarding" || queryParams.onboarding === "true", isSurvey = queryParams.onboarding === "survey", hasCompletedSurvey = await new Promise((resolve) => {
|
|
18
|
+
let unsubscribe = checklistStore.onStateChange(({ loaded, items }) => {
|
|
19
|
+
loaded && (unsubscribe(), resolve(items.onboardingSurvey.status === "accepted"));
|
|
20
|
+
});
|
|
29
21
|
});
|
|
22
|
+
if (isSurvey)
|
|
23
|
+
return hasCompletedSurvey ? null : render(React.createElement(Survey, { api }));
|
|
24
|
+
if (await new Promise((resolve) => api.once(STORY_SPECIFIED, resolve)), !(!!api.getData("example-button--primary") || !!document.getElementById("example-button--primary"))) {
|
|
25
|
+
console.warn(
|
|
26
|
+
"[@storybook/addon-onboarding] It seems like you have finished the onboarding experience in Storybook! Therefore this addon is not necessary anymore and will not be loaded. You are free to remove it from your project. More info: https://github.com/storybookjs/storybook/tree/next/code/addons/onboarding#uninstalling"
|
|
27
|
+
);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (!(!isOnboarding || window.innerWidth < 730))
|
|
31
|
+
return api.togglePanel(!0), api.togglePanelPosition("bottom"), api.setSelectedPanel(ADDON_CONTROLS_ID), render(React.createElement(Onboarding, { api, hasCompletedSurvey }));
|
|
30
32
|
});
|
package/dist/preset.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import CJS_COMPAT_NODE_URL_cky4rmco7i6 from 'node:url';
|
|
2
|
+
import CJS_COMPAT_NODE_PATH_cky4rmco7i6 from 'node:path';
|
|
3
|
+
import CJS_COMPAT_NODE_MODULE_cky4rmco7i6 from "node:module";
|
|
4
4
|
|
|
5
|
-
var __filename =
|
|
6
|
-
var __dirname =
|
|
7
|
-
var require =
|
|
5
|
+
var __filename = CJS_COMPAT_NODE_URL_cky4rmco7i6.fileURLToPath(import.meta.url);
|
|
6
|
+
var __dirname = CJS_COMPAT_NODE_PATH_cky4rmco7i6.dirname(__filename);
|
|
7
|
+
var require = CJS_COMPAT_NODE_MODULE_cky4rmco7i6.createRequire(import.meta.url);
|
|
8
8
|
|
|
9
9
|
// ------------------------------------------------------------
|
|
10
10
|
// end of CJS compatibility banner, injected by Storybook's esbuild configuration
|
|
@@ -14,15 +14,15 @@ var require = CJS_COMPAT_NODE_MODULE_q5ovexczp2c.createRequire(import.meta.url);
|
|
|
14
14
|
import { telemetry } from "storybook/internal/telemetry";
|
|
15
15
|
|
|
16
16
|
// package.json
|
|
17
|
-
var version = "10.1.0-alpha.
|
|
17
|
+
var version = "10.1.0-alpha.14";
|
|
18
18
|
|
|
19
19
|
// src/constants.ts
|
|
20
|
-
var
|
|
20
|
+
var ADDON_ID = "storybook/onboarding", ADDON_ONBOARDING_CHANNEL = `${ADDON_ID}/channel`;
|
|
21
21
|
|
|
22
22
|
// src/preset.ts
|
|
23
23
|
var experimental_serverChannel = async (channel, options) => {
|
|
24
24
|
let { disableTelemetry } = await options.presets.apply("core", {});
|
|
25
|
-
return disableTelemetry || channel.on(
|
|
25
|
+
return disableTelemetry || channel.on(ADDON_ONBOARDING_CHANNEL, ({ type, ...event }) => {
|
|
26
26
|
type === "telemetry" ? telemetry("addon-onboarding", { ...event, addonVersion: version }) : type === "survey" && telemetry("onboarding-survey", { ...event, addonVersion: version });
|
|
27
27
|
}), channel;
|
|
28
28
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storybook/addon-onboarding",
|
|
3
|
-
"version": "10.1.0-alpha.
|
|
3
|
+
"version": "10.1.0-alpha.14",
|
|
4
4
|
"description": "Storybook Onboarding: Help new users learn how to write stories",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"storybook",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"typescript": "^5.8.3"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
|
-
"storybook": "^10.1.0-alpha.
|
|
62
|
+
"storybook": "^10.1.0-alpha.14"
|
|
63
63
|
},
|
|
64
64
|
"publishConfig": {
|
|
65
65
|
"access": "public"
|