@storybook/addon-onboarding 0.0.0-pr-32939-sha-3f0b505a → 0.0.0-pr-32799-sha-e72c6b25

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.
@@ -1,3 +1,6 @@
1
+ import {
2
+ IntentSurvey
3
+ } from "./chunk-2GE6IOLL.js";
1
4
  import {
2
5
  ADDON_CONTROLS_ID,
3
6
  STORYBOOK_ADDON_ONBOARDING_CHANNEL
@@ -1250,10 +1253,10 @@ var require_prop_types = __commonJS({
1250
1253
  });
1251
1254
 
1252
1255
  // src/Onboarding.tsx
1253
- import React15, { useCallback as useCallback2, useEffect as useEffect5, useState as useState4 } from "react";
1256
+ import React14, { useCallback as useCallback2, useEffect as useEffect5, useState as useState3 } from "react";
1254
1257
  import { SyntaxHighlighter } from "storybook/internal/components";
1255
1258
  import { SAVE_STORY_RESPONSE } from "storybook/internal/core-events";
1256
- import { ThemeProvider, convert, styled as styled6, themes } from "storybook/theming";
1259
+ import { ThemeProvider, convert, styled as styled5, themes } from "storybook/theming";
1257
1260
 
1258
1261
  // src/components/Confetti/Confetti.tsx
1259
1262
  import React from "react";
@@ -7683,190 +7686,10 @@ function GuidedTour({
7683
7686
  }
7684
7687
  __name(GuidedTour, "GuidedTour");
7685
7688
 
7686
- // src/features/IntentSurvey/IntentSurvey.tsx
7687
- import React13, { useState as useState2 } from "react";
7688
- import { Button as Button3, Form, Modal } from "storybook/internal/components";
7689
- import { styled as styled4 } from "storybook/theming";
7690
-
7691
- // ../../.storybook/isChromatic.ts
7692
- function isChromatic(windowArg) {
7693
- const windowToCheck = windowArg || typeof window !== "undefined" && window;
7694
- return !!(windowToCheck && (windowToCheck.navigator.userAgent.match(/Chromatic/) || windowToCheck.location.href.match(/chromatic=true/)));
7695
- }
7696
- __name(isChromatic, "isChromatic");
7697
-
7698
- // src/features/IntentSurvey/IntentSurvey.tsx
7699
- var Content = styled4(Modal.Content)(({ theme: theme2 }) => ({
7700
- fontSize: theme2.typography.size.s2,
7701
- color: theme2.color.defaultText,
7702
- gap: 8
7703
- }));
7704
- var Row = styled4.div({
7705
- display: "grid",
7706
- gridTemplateColumns: "1fr 1fr",
7707
- gap: 14,
7708
- marginBottom: 8
7709
- });
7710
- var Question = styled4.div(({ theme: theme2 }) => ({
7711
- marginTop: 8,
7712
- marginBottom: 2,
7713
- fontWeight: theme2.typography.weight.bold
7714
- }));
7715
- var Label = styled4.label({
7716
- display: "flex",
7717
- gap: 8,
7718
- '&:has(input[type="checkbox"]:not(:disabled), input[type="radio"]:not(:disabled))': {
7719
- cursor: "pointer"
7720
- }
7721
- });
7722
- var Actions = styled4(Modal.Actions)({
7723
- marginTop: 8
7724
- });
7725
- var Checkbox = styled4(Form.Checkbox)({
7726
- margin: 2
7727
- });
7728
- var IntentSurvey = /* @__PURE__ */ __name(({
7729
- onComplete,
7730
- onDismiss
7731
- }) => {
7732
- const [isSubmitting, setIsSubmitting] = useState2(false);
7733
- const [formFields, setFormFields] = useState2({
7734
- building: {
7735
- label: "What are you building?",
7736
- type: "checkbox",
7737
- required: true,
7738
- options: shuffleObject({
7739
- "design-system": { label: "Design system" },
7740
- "application-ui": { label: "Application UI" }
7741
- }),
7742
- values: {
7743
- "design-system": false,
7744
- "application-ui": false
7745
- }
7746
- },
7747
- interest: {
7748
- label: "Which of these are you interested in?",
7749
- type: "checkbox",
7750
- required: true,
7751
- options: shuffleObject({
7752
- "ui-documentation": { label: "Generating UI docs" },
7753
- "functional-testing": { label: "Functional testing" },
7754
- "accessibility-testing": { label: "Accessibility testing" },
7755
- "visual-testing": { label: "Visual testing" },
7756
- "ai-augmented-development": { label: "Building UI with AI" },
7757
- "team-collaboration": { label: "Team collaboration" },
7758
- "design-handoff": { label: "Design handoff" }
7759
- }),
7760
- values: {
7761
- "ui-documentation": false,
7762
- "functional-testing": false,
7763
- "accessibility-testing": false,
7764
- "visual-testing": false,
7765
- "ai-augmented-development": false,
7766
- "team-collaboration": false,
7767
- "design-handoff": false
7768
- }
7769
- },
7770
- referrer: {
7771
- label: "How did you discover Storybook?",
7772
- type: "select",
7773
- required: true,
7774
- options: shuffleObject({
7775
- "we-use-it-at-work": { label: "We use it at work" },
7776
- "via-friend-or-colleague": { label: "Via friend or colleague" },
7777
- "via-social-media": { label: "Via social media" },
7778
- youtube: { label: "YouTube" },
7779
- "web-search": { label: "Web Search" },
7780
- "ai-agent": { label: "AI Agent (e.g. ChatGPT)" }
7781
- }),
7782
- values: {
7783
- "we-use-it-at-work": false,
7784
- "via-friend-or-colleague": false,
7785
- "via-social-media": false,
7786
- youtube: false,
7787
- "web-search": false,
7788
- "ai-agent": false
7789
- }
7790
- }
7791
- });
7792
- const updateFormData = /* @__PURE__ */ __name((key, optionOrValue, value) => {
7793
- const field = formFields[key];
7794
- setFormFields((fields) => {
7795
- if (field.type === "checkbox") {
7796
- const values = { ...field.values, [optionOrValue]: !!value };
7797
- return { ...fields, [key]: { ...field, values } };
7798
- }
7799
- if (field.type === "select") {
7800
- const values = Object.fromEntries(
7801
- Object.entries(field.values).map(([opt]) => [opt, opt === optionOrValue])
7802
- );
7803
- return { ...fields, [key]: { ...field, values } };
7804
- }
7805
- return fields;
7806
- });
7807
- }, "updateFormData");
7808
- const isValid = Object.values(formFields).every((field) => {
7809
- if (!field.required) {
7810
- return true;
7811
- }
7812
- return Object.values(field.values).some((value) => value === true);
7813
- });
7814
- const onSubmitForm = /* @__PURE__ */ __name((e2) => {
7815
- if (!isValid) {
7816
- return;
7817
- }
7818
- e2.preventDefault();
7819
- setIsSubmitting(true);
7820
- onComplete(
7821
- Object.fromEntries(Object.entries(formFields).map(([key, field]) => [key, field.values]))
7822
- );
7823
- }, "onSubmitForm");
7824
- return React13.createElement(Modal, { defaultOpen: true, width: 420, onEscapeKeyDown: onDismiss }, React13.createElement(Form, { onSubmit: onSubmitForm, id: "intent-survey-form" }, React13.createElement(Content, null, React13.createElement(Modal.Header, null, React13.createElement(Modal.Title, null, "Help improve Storybook")), Object.keys(formFields).map((key) => {
7825
- const field = formFields[key];
7826
- return React13.createElement(React13.Fragment, { key }, React13.createElement(Question, null, field.label), field.type === "checkbox" && React13.createElement(Row, null, Object.entries(field.options).map(([opt, option]) => {
7827
- const id = `${key}:${opt}`;
7828
- return React13.createElement("div", { key: id }, React13.createElement(Label, { htmlFor: id }, React13.createElement(
7829
- Checkbox,
7830
- {
7831
- name: id,
7832
- id,
7833
- checked: field.values[opt],
7834
- disabled: isSubmitting,
7835
- onChange: (e2) => updateFormData(key, opt, e2.target.checked)
7836
- }
7837
- ), option.label));
7838
- })), field.type === "select" && React13.createElement(
7839
- Form.Select,
7840
- {
7841
- name: key,
7842
- id: key,
7843
- value: Object.entries(field.values).find(([, isSelected]) => isSelected)?.[0] || "",
7844
- required: field.required,
7845
- disabled: isSubmitting,
7846
- onChange: (e2) => updateFormData(key, e2.target.value)
7847
- },
7848
- React13.createElement("option", { disabled: true, hidden: true, value: "" }, "Select an option..."),
7849
- Object.entries(field.options).map(([opt, option]) => React13.createElement("option", { key: opt, value: opt }, option.label))
7850
- ));
7851
- }), React13.createElement(Actions, null, React13.createElement(Button3, { disabled: isSubmitting || !isValid, size: "medium", type: "submit", variant: "solid" }, "Submit")))));
7852
- }, "IntentSurvey");
7853
- function shuffle(array) {
7854
- for (let i2 = array.length - 1; i2 > 0; i2--) {
7855
- const j = Math.floor(Math.random() * (i2 + 1));
7856
- [array[i2], array[j]] = [array[j], array[i2]];
7857
- }
7858
- return array;
7859
- }
7860
- __name(shuffle, "shuffle");
7861
- function shuffleObject(object) {
7862
- return isChromatic() ? object : Object.fromEntries(shuffle(Object.entries(object)));
7863
- }
7864
- __name(shuffleObject, "shuffleObject");
7865
-
7866
7689
  // src/features/SplashScreen/SplashScreen.tsx
7867
- import React14, { useCallback, useEffect as useEffect4, useState as useState3 } from "react";
7690
+ import React13, { useCallback, useEffect as useEffect4, useState as useState2 } from "react";
7868
7691
  import { ArrowRightIcon } from "@storybook/icons";
7869
- import { keyframes, styled as styled5 } from "storybook/theming";
7692
+ import { keyframes, styled as styled4 } from "storybook/theming";
7870
7693
  var fadeIn = keyframes({
7871
7694
  from: {
7872
7695
  opacity: 0
@@ -7903,7 +7726,7 @@ var rotate = keyframes({
7903
7726
  transform: "rotate(360deg)"
7904
7727
  }
7905
7728
  });
7906
- var Wrapper3 = styled5.div(({ visible }) => ({
7729
+ var Wrapper3 = styled4.div(({ visible }) => ({
7907
7730
  position: "fixed",
7908
7731
  top: 0,
7909
7732
  left: 0,
@@ -7916,7 +7739,7 @@ var Wrapper3 = styled5.div(({ visible }) => ({
7916
7739
  zIndex: 1e3,
7917
7740
  transition: "opacity 1s 0.5s"
7918
7741
  }));
7919
- var Backdrop = styled5.div({
7742
+ var Backdrop = styled4.div({
7920
7743
  position: "absolute",
7921
7744
  top: 0,
7922
7745
  left: 0,
@@ -7943,7 +7766,7 @@ var Backdrop = styled5.div({
7943
7766
  animation: `${rotate} 12s linear infinite`
7944
7767
  }
7945
7768
  });
7946
- var Content2 = styled5.div(({ visible }) => ({
7769
+ var Content = styled4.div(({ visible }) => ({
7947
7770
  position: "absolute",
7948
7771
  top: "50%",
7949
7772
  left: "50%",
@@ -7961,7 +7784,7 @@ var Content2 = styled5.div(({ visible }) => ({
7961
7784
  animation: `${slideIn} 1.5s 1s backwards`
7962
7785
  }
7963
7786
  }));
7964
- var Features = styled5.div({
7787
+ var Features = styled4.div({
7965
7788
  display: "flex",
7966
7789
  marginTop: 40,
7967
7790
  div: {
@@ -7984,7 +7807,7 @@ var Features = styled5.div({
7984
7807
  marginBottom: 10
7985
7808
  }
7986
7809
  });
7987
- var RadialButton = styled5.button({
7810
+ var RadialButton = styled4.button({
7988
7811
  display: "inline-flex",
7989
7812
  position: "relative",
7990
7813
  alignItems: "center",
@@ -8004,11 +7827,11 @@ var RadialButton = styled5.button({
8004
7827
  background: "rgba(255, 255, 255, 0.4)"
8005
7828
  }
8006
7829
  });
8007
- var ArrowIcon = styled5(ArrowRightIcon)({
7830
+ var ArrowIcon = styled4(ArrowRightIcon)({
8008
7831
  width: 30,
8009
7832
  color: "white"
8010
7833
  });
8011
- var ProgressCircle = styled5.svg(({ progress }) => ({
7834
+ var ProgressCircle = styled4.svg(({ progress }) => ({
8012
7835
  position: "absolute",
8013
7836
  top: -1,
8014
7837
  left: -1,
@@ -8028,8 +7851,8 @@ var ProgressCircle = styled5.svg(({ progress }) => ({
8028
7851
  }
8029
7852
  }));
8030
7853
  var SplashScreen = /* @__PURE__ */ __name(({ onDismiss, duration = 6e3 }) => {
8031
- const [progress, setProgress] = useState3(-4e3 * 100 / duration);
8032
- const [visible, setVisible] = useState3(true);
7854
+ const [progress, setProgress] = useState2(-4e3 * 100 / duration);
7855
+ const [visible, setVisible] = useState2(true);
8033
7856
  const ready = progress >= 100;
8034
7857
  const dismiss = useCallback(() => {
8035
7858
  setVisible(false);
@@ -8050,26 +7873,26 @@ var SplashScreen = /* @__PURE__ */ __name(({ onDismiss, duration = 6e3 }) => {
8050
7873
  dismiss();
8051
7874
  }
8052
7875
  }, [ready, dismiss]);
8053
- return React14.createElement(Wrapper3, { visible }, React14.createElement(Backdrop, null), React14.createElement(Content2, { visible }, React14.createElement("h1", null, "Meet your new frontend workshop"), React14.createElement(Features, null, React14.createElement("div", null, React14.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "33", height: "32" }, React14.createElement(
7876
+ return React13.createElement(Wrapper3, { visible }, React13.createElement(Backdrop, null), React13.createElement(Content, { visible }, React13.createElement("h1", null, "Meet your new frontend workshop"), React13.createElement(Features, null, React13.createElement("div", null, React13.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "33", height: "32" }, React13.createElement(
8054
7877
  "path",
8055
7878
  {
8056
7879
  d: "M4.06 0H32.5v28.44h-3.56V32H.5V3.56h3.56V0Zm21.33 7.11H4.06v21.33h21.33V7.11Z",
8057
7880
  fill: "currentColor"
8058
7881
  }
8059
- )), "Development"), React14.createElement("div", null, React14.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "32", height: "32" }, React14.createElement(
7882
+ )), "Development"), React13.createElement("div", null, React13.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "32", height: "32" }, React13.createElement(
8060
7883
  "path",
8061
7884
  {
8062
7885
  d: "M15.95 32c-1.85 0-3.1-1.55-3.1-3.54 0-1.1.45-2.78 1.35-5.03.9-2.3 1.35-4.51 1.35-6.81a22.21 22.21 0 0 0-5.1 3.67c-2.5 2.47-4.95 4.9-7.55 4.9-1.6 0-2.9-1.1-2.9-2.43 0-1.46 1.35-2.91 4.3-3.62 1.45-.36 3.1-.75 4.95-1.06 1.8-.31 3.8-1.02 5.9-2.08a23.77 23.77 0 0 0-6.1-2.12C5.3 13.18 2.3 12.6 1 11.28.35 10.6 0 9.9 0 9.14 0 7.82 1.2 6.8 2.95 6.8c2.65 0 5.75 3.1 7.95 5.3 1.1 1.1 2.65 2.21 4.65 3.27v-.57c0-1.77-.15-3.23-.55-4.3-.8-2.11-2.05-5.43-2.05-6.97 0-2.04 1.3-3.54 3.1-3.54 1.75 0 3.1 1.41 3.1 3.54 0 1.06-.45 2.78-1.35 5.12-.9 2.35-1.35 4.6-1.35 6.72 2.85-1.59 2.5-1.41 4.95-3.5 2.35-2.29 4-3.7 4.9-4.23.95-.58 1.9-.84 2.9-.84 1.6 0 2.8.97 2.8 2.34 0 1.5-1.25 2.78-4.15 3.62-1.4.4-3.05.75-4.9 1.1-1.9.36-3.9 1.07-6.1 2.13a23.3 23.3 0 0 0 5.95 2.08c3.65.7 6.75 1.32 8.15 2.6.7.67 1.05 1.33 1.05 2.08 0 1.33-1.2 2.43-2.95 2.43-2.95 0-6.75-4.15-8.2-5.61-.7-.7-2.2-1.72-4.4-2.96v.57c0 1.9.45 4.03 1.3 6.32.85 2.3 1.3 3.94 1.3 4.95 0 2.08-1.35 3.54-3.1 3.54Z",
8063
7886
  fill: "currentColor"
8064
7887
  }
8065
- )), "Testing"), React14.createElement("div", null, React14.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "33", height: "32" }, React14.createElement(
7888
+ )), "Testing"), React13.createElement("div", null, React13.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "33", height: "32" }, React13.createElement(
8066
7889
  "path",
8067
7890
  {
8068
7891
  d: "M.5 16a16 16 0 1 1 32 0 16 16 0 0 1-32 0Zm16 12.44A12.44 12.44 0 0 1 4.3 13.53a8 8 0 1 0 9.73-9.73 12.44 12.44 0 1 1 2.47 24.64ZM12.06 16a4.44 4.44 0 1 1 0-8.89 4.44 4.44 0 0 1 0 8.89Z",
8069
7892
  fill: "currentColor",
8070
7893
  fillRule: "evenodd"
8071
7894
  }
8072
- )), "Documentation")), React14.createElement(RadialButton, { onClick: dismiss }, React14.createElement(ArrowIcon, null), React14.createElement(ProgressCircle, { xmlns: "http://www.w3.org/2000/svg" }, React14.createElement("circle", null)), React14.createElement(ProgressCircle, { xmlns: "http://www.w3.org/2000/svg", progress: true }, React14.createElement(
7895
+ )), "Documentation")), React13.createElement(RadialButton, { onClick: dismiss }, React13.createElement(ArrowIcon, null), React13.createElement(ProgressCircle, { xmlns: "http://www.w3.org/2000/svg" }, React13.createElement("circle", null)), React13.createElement(ProgressCircle, { xmlns: "http://www.w3.org/2000/svg", progress: true }, React13.createElement(
8073
7896
  "circle",
8074
7897
  {
8075
7898
  strokeDashoffset: Math.PI * 48 * (1 - Math.max(0, Math.min(progress, 100)) / 100)
@@ -8078,7 +7901,7 @@ var SplashScreen = /* @__PURE__ */ __name(({ onDismiss, duration = 6e3 }) => {
8078
7901
  }, "SplashScreen");
8079
7902
 
8080
7903
  // src/Onboarding.tsx
8081
- var SpanHighlight = styled6.span(({ theme: theme2 }) => ({
7904
+ var SpanHighlight = styled5.span(({ theme: theme2 }) => ({
8082
7905
  display: "inline-flex",
8083
7906
  borderRadius: 3,
8084
7907
  padding: "0 5px",
@@ -8092,7 +7915,7 @@ var SpanHighlight = styled6.span(({ theme: theme2 }) => ({
8092
7915
  boxSizing: "border-box",
8093
7916
  lineHeight: "17px"
8094
7917
  }));
8095
- var CodeWrapper = styled6.div(({ theme: theme2 }) => ({
7918
+ var CodeWrapper = styled5.div(({ theme: theme2 }) => ({
8096
7919
  background: theme2.background.content,
8097
7920
  borderRadius: 3,
8098
7921
  marginTop: 15,
@@ -8104,13 +7927,13 @@ var CodeWrapper = styled6.div(({ theme: theme2 }) => ({
8104
7927
  }));
8105
7928
  var theme = convert();
8106
7929
  function Onboarding({ api }) {
8107
- const [enabled, setEnabled] = useState4(true);
8108
- const [showConfetti, setShowConfetti] = useState4(false);
8109
- const [step, setStep] = useState4("1:Intro");
8110
- const [primaryControl, setPrimaryControl] = useState4();
8111
- const [saveFromControls, setSaveFromControls] = useState4();
8112
- const [createNewStoryForm, setCreateNewStoryForm] = useState4();
8113
- const [createdStory, setCreatedStory] = useState4();
7930
+ const [enabled, setEnabled] = useState3(true);
7931
+ const [showConfetti, setShowConfetti] = useState3(false);
7932
+ const [step, setStep] = useState3("1:Intro");
7933
+ const [primaryControl, setPrimaryControl] = useState3();
7934
+ const [saveFromControls, setSaveFromControls] = useState3();
7935
+ const [createNewStoryForm, setCreateNewStoryForm] = useState3();
7936
+ const [createdStory, setCreatedStory] = useState3();
8114
7937
  const userAgent = globalThis?.navigator?.userAgent;
8115
7938
  const selectStory = useCallback2(
8116
7939
  (storyId) => {
@@ -8124,14 +7947,24 @@ function Onboarding({ api }) {
8124
7947
  },
8125
7948
  [api]
8126
7949
  );
8127
- const disableOnboarding = useCallback2(() => {
8128
- const url = new URL(window.location.href);
8129
- const path = decodeURIComponent(url.searchParams.get("path"));
8130
- url.search = `?path=${path}&onboarding=false`;
8131
- history.replaceState({}, "", url.href);
8132
- api.setQueryParams({ onboarding: "false" });
8133
- setEnabled(false);
8134
- }, [api, setEnabled]);
7950
+ const disableOnboarding = useCallback2(
7951
+ (dismissedStep) => {
7952
+ if (dismissedStep) {
7953
+ api.emit(STORYBOOK_ADDON_ONBOARDING_CHANNEL, {
7954
+ step: dismissedStep,
7955
+ type: "dismiss",
7956
+ userAgent
7957
+ });
7958
+ }
7959
+ const url = new URL(window.location.href);
7960
+ const path = decodeURIComponent(url.searchParams.get("path"));
7961
+ url.search = `?path=${path}&onboarding=false`;
7962
+ history.replaceState({}, "", url.href);
7963
+ api.setQueryParams({ onboarding: "false" });
7964
+ setEnabled(false);
7965
+ },
7966
+ [api, setEnabled, userAgent]
7967
+ );
8135
7968
  const completeOnboarding = useCallback2(
8136
7969
  (answers) => {
8137
7970
  api.emit(STORYBOOK_ADDON_ONBOARDING_CHANNEL, {
@@ -8210,7 +8043,7 @@ function Onboarding({ api }) {
8210
8043
  key: "2:Controls",
8211
8044
  target: "#control-primary",
8212
8045
  title: "Interactive story playground",
8213
- content: React15.createElement(React15.Fragment, null, "See how a story renders with different data and state without touching code. Try it out by toggling this button.", React15.createElement(HighlightElement, { targetSelector: "#control-primary", pulsating: true })),
8046
+ content: React14.createElement(React14.Fragment, null, "See how a story renders with different data and state without touching code. Try it out by toggling this button.", React14.createElement(HighlightElement, { targetSelector: "#control-primary", pulsating: true })),
8214
8047
  offset: 20,
8215
8048
  placement: "right",
8216
8049
  disableBeacon: true,
@@ -8225,7 +8058,7 @@ function Onboarding({ api }) {
8225
8058
  key: "3:SaveFromControls",
8226
8059
  target: 'button[aria-label="Create new story with these settings"]',
8227
8060
  title: "Save your changes as a new story",
8228
- content: React15.createElement(React15.Fragment, null, "Great! Storybook stories represent the key states of each of your components. After modifying a story, you can save your changes from here or reset it.", React15.createElement(HighlightElement, { targetSelector: "button[aria-label='Create new story with these settings']" })),
8061
+ content: React14.createElement(React14.Fragment, null, "Great! Storybook stories represent the key states of each of your components. After modifying a story, you can save your changes from here or reset it.", React14.createElement(HighlightElement, { targetSelector: "button[aria-label='Create new story with these settings']" })),
8229
8062
  offset: 6,
8230
8063
  placement: "top",
8231
8064
  disableBeacon: true,
@@ -8247,7 +8080,7 @@ function Onboarding({ api }) {
8247
8080
  key: "5:StoryCreated",
8248
8081
  target: '#storybook-explorer-tree [data-selected="true"]',
8249
8082
  title: "You just added your first story!",
8250
- content: React15.createElement(React15.Fragment, null, "Well done! You just created your first story from the Storybook manager. This automatically added a few lines of code in", " ", React15.createElement(SpanHighlight, null, createdStory?.sourceFileName), ".", snippet && React15.createElement(ThemeProvider, { theme: convert(themes.dark) }, React15.createElement(CodeWrapper, null, React15.createElement(
8083
+ content: React14.createElement(React14.Fragment, null, "Well done! You just created your first story from the Storybook manager. This automatically added a few lines of code in", " ", React14.createElement(SpanHighlight, null, createdStory?.sourceFileName), ".", snippet && React14.createElement(ThemeProvider, { theme: convert(themes.dark) }, React14.createElement(CodeWrapper, null, React14.createElement(
8251
8084
  SyntaxHighlighter,
8252
8085
  {
8253
8086
  language: "jsx",
@@ -8267,12 +8100,18 @@ function Onboarding({ api }) {
8267
8100
  }
8268
8101
  }
8269
8102
  ];
8270
- return React15.createElement(ThemeProvider, { theme }, showConfetti && React15.createElement(Confetti, null), step === "1:Intro" ? React15.createElement(SplashScreen, { onDismiss: () => setStep("2:Controls") }) : step === "6:IntentSurvey" ? React15.createElement(IntentSurvey, { onComplete: completeOnboarding, onDismiss: disableOnboarding }) : React15.createElement(
8103
+ return React14.createElement(ThemeProvider, { theme }, showConfetti && React14.createElement(Confetti, null), step === "1:Intro" ? React14.createElement(SplashScreen, { onDismiss: () => setStep("2:Controls") }) : step === "6:IntentSurvey" ? React14.createElement(
8104
+ IntentSurvey,
8105
+ {
8106
+ onComplete: completeOnboarding,
8107
+ onDismiss: () => disableOnboarding("6:IntentSurvey")
8108
+ }
8109
+ ) : React14.createElement(
8271
8110
  GuidedTour,
8272
8111
  {
8273
8112
  step,
8274
8113
  steps,
8275
- onClose: disableOnboarding,
8114
+ onClose: () => disableOnboarding(step),
8276
8115
  onComplete: () => setStep("6:IntentSurvey")
8277
8116
  }
8278
8117
  ));
@@ -0,0 +1,46 @@
1
+ import {
2
+ IntentSurvey
3
+ } from "./chunk-2GE6IOLL.js";
4
+ import {
5
+ STORYBOOK_ADDON_ONBOARDING_CHANNEL
6
+ } from "./chunk-B266DSPW.js";
7
+ import {
8
+ __name
9
+ } from "./chunk-CBI7MY27.js";
10
+
11
+ // src/Survey.tsx
12
+ import React, { useCallback } from "react";
13
+ import { ThemeProvider, convert } from "storybook/theming";
14
+ var theme = convert();
15
+ function Survey({ api }) {
16
+ const userAgent = globalThis?.navigator?.userAgent;
17
+ const disableOnboarding = useCallback(() => {
18
+ const url = new URL(window.location.href);
19
+ const path = decodeURIComponent(url.searchParams.get("path"));
20
+ url.search = `?path=${path}&onboarding=false`;
21
+ history.replaceState({}, "", url.href);
22
+ api.setQueryParams({ onboarding: "false" });
23
+ }, [api]);
24
+ const complete = useCallback(
25
+ (answers) => {
26
+ api.emit(STORYBOOK_ADDON_ONBOARDING_CHANNEL, {
27
+ answers,
28
+ type: "survey",
29
+ userAgent
30
+ });
31
+ disableOnboarding();
32
+ },
33
+ [api, disableOnboarding, userAgent]
34
+ );
35
+ const dismiss = useCallback(() => {
36
+ api.emit(STORYBOOK_ADDON_ONBOARDING_CHANNEL, {
37
+ type: "skipSurvey"
38
+ });
39
+ disableOnboarding();
40
+ }, [api, disableOnboarding]);
41
+ return React.createElement(ThemeProvider, { theme }, React.createElement(IntentSurvey, { onComplete: complete, onDismiss: dismiss }));
42
+ }
43
+ __name(Survey, "Survey");
44
+ export {
45
+ Survey as default
46
+ };
@@ -0,0 +1,187 @@
1
+ import {
2
+ __name
3
+ } from "./chunk-CBI7MY27.js";
4
+
5
+ // src/features/IntentSurvey/IntentSurvey.tsx
6
+ import React, { useState } from "react";
7
+ import { Button, Form, Modal } from "storybook/internal/components";
8
+ import { styled } from "storybook/theming";
9
+
10
+ // ../../.storybook/isChromatic.ts
11
+ function isChromatic(windowArg) {
12
+ const windowToCheck = windowArg || typeof window !== "undefined" && window;
13
+ return !!(windowToCheck && (windowToCheck.navigator.userAgent.match(/Chromatic/) || windowToCheck.location.href.match(/chromatic=true/)));
14
+ }
15
+ __name(isChromatic, "isChromatic");
16
+
17
+ // src/features/IntentSurvey/IntentSurvey.tsx
18
+ var Content = styled(Modal.Content)(({ theme }) => ({
19
+ fontSize: theme.typography.size.s2,
20
+ color: theme.color.defaultText,
21
+ gap: 8
22
+ }));
23
+ var Row = styled.div({
24
+ display: "grid",
25
+ gridTemplateColumns: "1fr 1fr",
26
+ gap: 14,
27
+ marginBottom: 8
28
+ });
29
+ var Question = styled.div(({ theme }) => ({
30
+ marginTop: 8,
31
+ marginBottom: 2,
32
+ fontWeight: theme.typography.weight.bold
33
+ }));
34
+ var Label = styled.label({
35
+ display: "flex",
36
+ gap: 8,
37
+ '&:has(input[type="checkbox"]:not(:disabled), input[type="radio"]:not(:disabled))': {
38
+ cursor: "pointer"
39
+ }
40
+ });
41
+ var Actions = styled(Modal.Actions)({
42
+ marginTop: 8
43
+ });
44
+ var Checkbox = styled(Form.Checkbox)({
45
+ margin: 2
46
+ });
47
+ var IntentSurvey = /* @__PURE__ */ __name(({
48
+ onComplete,
49
+ onDismiss
50
+ }) => {
51
+ const [isSubmitting, setIsSubmitting] = useState(false);
52
+ const [formFields, setFormFields] = useState({
53
+ building: {
54
+ label: "What are you building?",
55
+ type: "checkbox",
56
+ required: true,
57
+ options: shuffleObject({
58
+ "design-system": { label: "Design system" },
59
+ "application-ui": { label: "Application UI" }
60
+ }),
61
+ values: {
62
+ "design-system": false,
63
+ "application-ui": false
64
+ }
65
+ },
66
+ interest: {
67
+ label: "Which of these are you interested in?",
68
+ type: "checkbox",
69
+ required: true,
70
+ options: shuffleObject({
71
+ "ui-documentation": { label: "Generating UI docs" },
72
+ "functional-testing": { label: "Functional testing" },
73
+ "accessibility-testing": { label: "Accessibility testing" },
74
+ "visual-testing": { label: "Visual testing" },
75
+ "ai-augmented-development": { label: "Building UI with AI" },
76
+ "team-collaboration": { label: "Team collaboration" },
77
+ "design-handoff": { label: "Design handoff" }
78
+ }),
79
+ values: {
80
+ "ui-documentation": false,
81
+ "functional-testing": false,
82
+ "accessibility-testing": false,
83
+ "visual-testing": false,
84
+ "ai-augmented-development": false,
85
+ "team-collaboration": false,
86
+ "design-handoff": false
87
+ }
88
+ },
89
+ referrer: {
90
+ label: "How did you discover Storybook?",
91
+ type: "select",
92
+ required: true,
93
+ options: shuffleObject({
94
+ "we-use-it-at-work": { label: "We use it at work" },
95
+ "via-friend-or-colleague": { label: "Via friend or colleague" },
96
+ "via-social-media": { label: "Via social media" },
97
+ youtube: { label: "YouTube" },
98
+ "web-search": { label: "Web Search" },
99
+ "ai-agent": { label: "AI Agent (e.g. ChatGPT)" }
100
+ }),
101
+ values: {
102
+ "we-use-it-at-work": false,
103
+ "via-friend-or-colleague": false,
104
+ "via-social-media": false,
105
+ youtube: false,
106
+ "web-search": false,
107
+ "ai-agent": false
108
+ }
109
+ }
110
+ });
111
+ const updateFormData = /* @__PURE__ */ __name((key, optionOrValue, value) => {
112
+ const field = formFields[key];
113
+ setFormFields((fields) => {
114
+ if (field.type === "checkbox") {
115
+ const values = { ...field.values, [optionOrValue]: !!value };
116
+ return { ...fields, [key]: { ...field, values } };
117
+ }
118
+ if (field.type === "select") {
119
+ const values = Object.fromEntries(
120
+ Object.entries(field.values).map(([opt]) => [opt, opt === optionOrValue])
121
+ );
122
+ return { ...fields, [key]: { ...field, values } };
123
+ }
124
+ return fields;
125
+ });
126
+ }, "updateFormData");
127
+ const isValid = Object.values(formFields).every((field) => {
128
+ if (!field.required) {
129
+ return true;
130
+ }
131
+ return Object.values(field.values).some((value) => value === true);
132
+ });
133
+ const onSubmitForm = /* @__PURE__ */ __name((e) => {
134
+ if (!isValid) {
135
+ return;
136
+ }
137
+ e.preventDefault();
138
+ setIsSubmitting(true);
139
+ onComplete(
140
+ Object.fromEntries(Object.entries(formFields).map(([key, field]) => [key, field.values]))
141
+ );
142
+ }, "onSubmitForm");
143
+ return React.createElement(Modal, { defaultOpen: true, width: 420, onEscapeKeyDown: onDismiss }, React.createElement(Form, { onSubmit: onSubmitForm, 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) => {
144
+ const field = formFields[key];
145
+ return React.createElement(React.Fragment, { key }, React.createElement(Question, null, field.label), field.type === "checkbox" && React.createElement(Row, null, Object.entries(field.options).map(([opt, option]) => {
146
+ const id = `${key}:${opt}`;
147
+ return React.createElement("div", { key: id }, React.createElement(Label, { htmlFor: id }, React.createElement(
148
+ Checkbox,
149
+ {
150
+ name: id,
151
+ id,
152
+ checked: field.values[opt],
153
+ disabled: isSubmitting,
154
+ onChange: (e) => updateFormData(key, opt, e.target.checked)
155
+ }
156
+ ), option.label));
157
+ })), field.type === "select" && React.createElement(
158
+ Form.Select,
159
+ {
160
+ name: key,
161
+ id: key,
162
+ value: Object.entries(field.values).find(([, isSelected]) => isSelected)?.[0] || "",
163
+ required: field.required,
164
+ disabled: isSubmitting,
165
+ onChange: (e) => updateFormData(key, e.target.value)
166
+ },
167
+ React.createElement("option", { disabled: true, hidden: true, value: "" }, "Select an option..."),
168
+ Object.entries(field.options).map(([opt, option]) => React.createElement("option", { key: opt, value: opt }, option.label))
169
+ ));
170
+ }), React.createElement(Actions, null, React.createElement(Button, { disabled: isSubmitting || !isValid, size: "medium", type: "submit", variant: "solid" }, "Submit")))));
171
+ }, "IntentSurvey");
172
+ function shuffle(array) {
173
+ for (let i = array.length - 1; i > 0; i--) {
174
+ const j = Math.floor(Math.random() * (i + 1));
175
+ [array[i], array[j]] = [array[j], array[i]];
176
+ }
177
+ return array;
178
+ }
179
+ __name(shuffle, "shuffle");
180
+ function shuffleObject(object) {
181
+ return isChromatic() ? object : Object.fromEntries(shuffle(Object.entries(object)));
182
+ }
183
+ __name(shuffleObject, "shuffleObject");
184
+
185
+ export {
186
+ IntentSurvey
187
+ };
package/dist/manager.js CHANGED
@@ -1,37 +1,46 @@
1
1
  import {
2
2
  ADDON_CONTROLS_ID
3
3
  } from "./_browser-chunks/chunk-B266DSPW.js";
4
- import "./_browser-chunks/chunk-CBI7MY27.js";
4
+ import {
5
+ __name
6
+ } from "./_browser-chunks/chunk-CBI7MY27.js";
5
7
 
6
8
  // src/manager.tsx
7
9
  import React, { Suspense, lazy } from "react";
8
- import ReactDOM from "react-dom";
10
+ import { createRoot } from "react-dom/client";
9
11
  import { STORY_SPECIFIED } from "storybook/internal/core-events";
10
12
  import { addons } from "storybook/manager-api";
11
- var Onboarding = lazy(() => import("./_browser-chunks/Onboarding-XBLXWDOE.js"));
13
+ var Onboarding = lazy(() => import("./_browser-chunks/Onboarding-JPHTTZDC.js"));
14
+ var Survey = lazy(() => import("./_browser-chunks/Survey-FXIM2EKF.js"));
15
+ var render = /* @__PURE__ */ __name((node) => {
16
+ let container = document.getElementById("storybook-addon-onboarding");
17
+ if (!container) {
18
+ container = document.createElement("div");
19
+ container.id = "storybook-addon-onboarding";
20
+ document.body.appendChild(container);
21
+ }
22
+ createRoot(container).render(React.createElement(Suspense, { fallback: React.createElement("div", null) }, node));
23
+ }, "render");
12
24
  addons.register("@storybook/addon-onboarding", async (api) => {
13
- const urlState = api.getUrlState();
14
- const isOnboarding = urlState.path === "/onboarding" || urlState.queryParams.onboarding === "true";
15
- api.once(STORY_SPECIFIED, () => {
16
- const hasButtonStories = !!api.getData("example-button--primary") || !!document.getElementById("example-button--primary");
17
- if (!hasButtonStories) {
18
- console.warn(
19
- `[@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`
20
- );
21
- return;
22
- }
23
- if (!isOnboarding || window.innerWidth < 730) {
24
- return;
25
- }
26
- api.togglePanel(true);
27
- api.togglePanelPosition("bottom");
28
- api.setSelectedPanel(ADDON_CONTROLS_ID);
29
- const domNode = document.createElement("div");
30
- domNode.id = "storybook-addon-onboarding";
31
- document.body.appendChild(domNode);
32
- ReactDOM.render(
33
- React.createElement(Suspense, { fallback: React.createElement("div", null) }, React.createElement(Onboarding, { api })),
34
- domNode
25
+ const { path, queryParams } = api.getUrlState();
26
+ const isOnboarding = path === "/onboarding" || queryParams.onboarding === "true";
27
+ const isSurvey = queryParams.onboarding === "survey";
28
+ if (isSurvey) {
29
+ return render(React.createElement(Survey, { api }));
30
+ }
31
+ await new Promise((resolve) => api.once(STORY_SPECIFIED, resolve));
32
+ const hasButtonStories = !!api.getData("example-button--primary") || !!document.getElementById("example-button--primary");
33
+ if (!hasButtonStories) {
34
+ console.warn(
35
+ `[@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`
35
36
  );
36
- });
37
+ return;
38
+ }
39
+ if (!isOnboarding || window.innerWidth < 730) {
40
+ return;
41
+ }
42
+ api.togglePanel(true);
43
+ api.togglePanelPosition("bottom");
44
+ api.setSelectedPanel(ADDON_CONTROLS_ID);
45
+ return render(React.createElement(Onboarding, { api }));
37
46
  });
package/dist/preset.js CHANGED
@@ -1,10 +1,10 @@
1
- import CJS_COMPAT_NODE_URL_n64ou0qpyda from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_n64ou0qpyda from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_n64ou0qpyda from "node:module";
1
+ import CJS_COMPAT_NODE_URL_3sdx6dbqxah from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_3sdx6dbqxah from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_3sdx6dbqxah from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_n64ou0qpyda.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_n64ou0qpyda.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_n64ou0qpyda.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_3sdx6dbqxah.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_3sdx6dbqxah.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_3sdx6dbqxah.createRequire(import.meta.url);
8
8
 
9
9
  // ------------------------------------------------------------
10
10
  // end of CJS compatibility banner, injected by Storybook's esbuild configuration
@@ -16,7 +16,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
16
16
  import { telemetry } from "storybook/internal/telemetry";
17
17
 
18
18
  // package.json
19
- var version = "0.0.0-pr-32939-sha-3f0b505a";
19
+ var version = "0.0.0-pr-32799-sha-e72c6b25";
20
20
 
21
21
  // src/constants.ts
22
22
  var STORYBOOK_ADDON_ONBOARDING_CHANNEL = "STORYBOOK_ADDON_ONBOARDING_CHANNEL";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/addon-onboarding",
3
- "version": "0.0.0-pr-32939-sha-3f0b505a",
3
+ "version": "0.0.0-pr-32799-sha-e72c6b25",
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": "^0.0.0-pr-32939-sha-3f0b505a"
62
+ "storybook": "^0.0.0-pr-32799-sha-e72c6b25"
63
63
  },
64
64
  "publishConfig": {
65
65
  "access": "public"