@waypointjs/builder 0.1.0 → 0.1.4

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.js CHANGED
@@ -3,6 +3,7 @@ import { useState, useRef, useEffect } from 'react';
3
3
  import { create } from 'zustand';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
5
  import { useWaypoint, useWaypointStep } from '@waypointjs/react';
6
+ import { DevPanel } from '@waypointjs/devtools';
6
7
 
7
8
  // src/components/WaypointBuilder.tsx
8
9
 
@@ -344,9 +345,19 @@ var useBuilderStore = create((set, _get) => ({
344
345
  isDirty: true
345
346
  }))
346
347
  }));
347
- var BLANK_FORM = { id: "", label: "", type: "string", blocking: false };
348
+ var BLANK_FORM = {
349
+ id: "",
350
+ label: "",
351
+ type: "string",
352
+ blocking: false
353
+ };
348
354
  function ExternalVariablePanel() {
349
- const { schema, addExternalVariable, updateExternalVariable, removeExternalVariable } = useBuilderStore();
355
+ const {
356
+ schema,
357
+ addExternalVariable,
358
+ updateExternalVariable,
359
+ removeExternalVariable
360
+ } = useBuilderStore();
350
361
  const variables = schema.externalVariables ?? [];
351
362
  const [isAdding, setIsAdding] = useState(false);
352
363
  const [editingId, setEditingId] = useState(null);
@@ -372,9 +383,11 @@ function ExternalVariablePanel() {
372
383
  }
373
384
  function validateForm() {
374
385
  if (!form.id.trim()) return "ID is required";
375
- if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(form.id.trim())) return "ID must be alphanumeric (no spaces)";
386
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(form.id.trim()))
387
+ return "ID must be alphanumeric (no spaces)";
376
388
  if (!form.label.trim()) return "Label is required";
377
- if (isAdding && variables.some((v) => v.id === form.id.trim())) return `ID "${form.id}" already exists`;
389
+ if (isAdding && variables.some((v) => v.id === form.id.trim()))
390
+ return `ID "${form.id}" already exists`;
378
391
  return null;
379
392
  }
380
393
  function submitAdd() {
@@ -383,7 +396,12 @@ function ExternalVariablePanel() {
383
396
  setError(err);
384
397
  return;
385
398
  }
386
- addExternalVariable({ id: form.id.trim(), label: form.label.trim(), type: form.type, blocking: form.blocking });
399
+ addExternalVariable({
400
+ id: form.id.trim(),
401
+ label: form.label.trim(),
402
+ type: form.type,
403
+ blocking: form.blocking
404
+ });
387
405
  setIsAdding(false);
388
406
  setForm(BLANK_FORM);
389
407
  setError(null);
@@ -395,7 +413,11 @@ function ExternalVariablePanel() {
395
413
  return;
396
414
  }
397
415
  if (!editingId) return;
398
- updateExternalVariable(editingId, { label: form.label.trim(), type: form.type, blocking: form.blocking });
416
+ updateExternalVariable(editingId, {
417
+ label: form.label.trim(),
418
+ type: form.type,
419
+ blocking: form.blocking
420
+ });
399
421
  setEditingId(null);
400
422
  setError(null);
401
423
  }
@@ -409,7 +431,15 @@ function ExternalVariablePanel() {
409
431
  return /* @__PURE__ */ jsxs("div", { style: panelStyle, children: [
410
432
  /* @__PURE__ */ jsxs("div", { style: headerStyle, children: [
411
433
  /* @__PURE__ */ jsx("span", { style: titleStyle, children: "External Variables" }),
412
- !isAdding && /* @__PURE__ */ jsx("button", { style: addBtnStyle, onClick: startAdd, title: "Add external variable", children: "+ Add" })
434
+ !isAdding && /* @__PURE__ */ jsx(
435
+ "button",
436
+ {
437
+ style: addBtnStyle,
438
+ onClick: startAdd,
439
+ title: "Add external variable",
440
+ children: "+ Add"
441
+ }
442
+ )
413
443
  ] }),
414
444
  variables.length === 0 && !isAdding && /* @__PURE__ */ jsxs("p", { style: emptyStyle, children: [
415
445
  "No external variables declared.",
@@ -423,37 +453,55 @@ function ExternalVariablePanel() {
423
453
  variables.map((v) => {
424
454
  const refs = usageMap.get(v.id) ?? [];
425
455
  const isBeingEdited = editingId === v.id;
426
- return /* @__PURE__ */ jsx("div", { style: { ...varRowStyle, ...isBeingEdited ? varRowActiveStyle : {} }, children: isBeingEdited ? /* @__PURE__ */ jsx(
427
- VarForm,
456
+ return /* @__PURE__ */ jsx(
457
+ "div",
428
458
  {
429
- form,
430
- onChange: setForm,
431
- error,
432
- onSubmit: submitEdit,
433
- onCancel: cancelForm,
434
- submitLabel: "Save",
435
- idReadOnly: true
436
- }
437
- ) : /* @__PURE__ */ jsxs(Fragment, { children: [
438
- /* @__PURE__ */ jsxs("div", { style: varMainStyle, children: [
439
- /* @__PURE__ */ jsxs("div", { style: varTopRowStyle, children: [
440
- /* @__PURE__ */ jsxs("span", { style: varIdStyle, children: [
441
- "$",
442
- `ext.${v.id}`
459
+ style: {
460
+ ...varRowStyle,
461
+ ...isBeingEdited ? varRowActiveStyle : {}
462
+ },
463
+ children: isBeingEdited ? /* @__PURE__ */ jsx(
464
+ VarForm,
465
+ {
466
+ form,
467
+ onChange: setForm,
468
+ error,
469
+ onSubmit: submitEdit,
470
+ onCancel: cancelForm,
471
+ submitLabel: "Save",
472
+ idReadOnly: true
473
+ }
474
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
475
+ /* @__PURE__ */ jsxs("div", { style: varMainStyle, children: [
476
+ /* @__PURE__ */ jsxs("div", { style: varTopRowStyle, children: [
477
+ /* @__PURE__ */ jsxs("span", { style: varIdStyle, children: [
478
+ "$",
479
+ `ext.${v.id}`
480
+ ] }),
481
+ /* @__PURE__ */ jsxs("div", { style: badgeRowStyle, children: [
482
+ /* @__PURE__ */ jsx(TypeBadge, { type: v.type }),
483
+ v.blocking && /* @__PURE__ */ jsx("span", { style: blockingBadgeStyle, children: "blocking" })
484
+ ] })
485
+ ] }),
486
+ /* @__PURE__ */ jsx("span", { style: varLabelStyle, children: v.label }),
487
+ refs.length > 0 && /* @__PURE__ */ jsx("div", { style: refsStyle, children: refs.map((ref, i) => /* @__PURE__ */ jsx("span", { style: refChipStyle, children: ref }, i)) })
443
488
  ] }),
444
- /* @__PURE__ */ jsxs("div", { style: badgeRowStyle, children: [
445
- /* @__PURE__ */ jsx(TypeBadge, { type: v.type }),
446
- v.blocking && /* @__PURE__ */ jsx("span", { style: blockingBadgeStyle, children: "blocking" })
489
+ /* @__PURE__ */ jsxs("div", { style: varActionsStyle, children: [
490
+ /* @__PURE__ */ jsx("button", { style: actionBtnStyle, onClick: () => startEdit(v), children: "Edit" }),
491
+ /* @__PURE__ */ jsx(
492
+ "button",
493
+ {
494
+ style: { ...actionBtnStyle, color: "#ef4444" },
495
+ title: "Remove variable",
496
+ onClick: () => remove(v.id),
497
+ children: "\u2715"
498
+ }
499
+ )
447
500
  ] })
448
- ] }),
449
- /* @__PURE__ */ jsx("span", { style: varLabelStyle, children: v.label }),
450
- refs.length > 0 && /* @__PURE__ */ jsx("div", { style: refsStyle, children: refs.map((ref, i) => /* @__PURE__ */ jsx("span", { style: refChipStyle, children: ref }, i)) })
451
- ] }),
452
- /* @__PURE__ */ jsxs("div", { style: varActionsStyle, children: [
453
- /* @__PURE__ */ jsx("button", { style: actionBtnStyle, onClick: () => startEdit(v), children: "Edit" }),
454
- /* @__PURE__ */ jsx("button", { style: { ...actionBtnStyle, color: "#ef4444" }, title: "Remove variable", onClick: () => remove(v.id), children: "\u2715" })
455
- ] })
456
- ] }) }, v.id);
501
+ ] })
502
+ },
503
+ v.id
504
+ );
457
505
  }),
458
506
  isAdding && /* @__PURE__ */ jsx("div", { style: { ...varRowStyle, ...varRowActiveStyle }, children: /* @__PURE__ */ jsx(
459
507
  VarForm,
@@ -468,7 +516,15 @@ function ExternalVariablePanel() {
468
516
  ) })
469
517
  ] });
470
518
  }
471
- function VarForm({ form, onChange, error, onSubmit, onCancel, submitLabel, idReadOnly }) {
519
+ function VarForm({
520
+ form,
521
+ onChange,
522
+ error,
523
+ onSubmit,
524
+ onCancel,
525
+ submitLabel,
526
+ idReadOnly
527
+ }) {
472
528
  function set(key, value) {
473
529
  onChange({ ...form, [key]: value });
474
530
  }
@@ -477,7 +533,10 @@ function VarForm({ form, onChange, error, onSubmit, onCancel, submitLabel, idRea
477
533
  /* @__PURE__ */ jsx(
478
534
  "input",
479
535
  {
480
- style: { ...inputStyle, ...idReadOnly ? { background: "#f9fafb", color: "#6b7280" } : {} },
536
+ style: {
537
+ ...inputStyle,
538
+ ...idReadOnly ? { background: "#f9fafb", color: "#6b7280" } : {}
539
+ },
481
540
  value: form.id,
482
541
  onChange: (e) => set("id", e.target.value),
483
542
  placeholder: "e.g. userId",
@@ -495,12 +554,20 @@ function VarForm({ form, onChange, error, onSubmit, onCancel, submitLabel, idRea
495
554
  }
496
555
  ),
497
556
  /* @__PURE__ */ jsx("label", { style: formLabelStyle, children: "Type" }),
498
- /* @__PURE__ */ jsxs("select", { style: selectStyle, value: form.type, onChange: (e) => set("type", e.target.value), children: [
499
- /* @__PURE__ */ jsx("option", { value: "string", children: "string" }),
500
- /* @__PURE__ */ jsx("option", { value: "number", children: "number" }),
501
- /* @__PURE__ */ jsx("option", { value: "boolean", children: "boolean" }),
502
- /* @__PURE__ */ jsx("option", { value: "object", children: "object" })
503
- ] }),
557
+ /* @__PURE__ */ jsxs(
558
+ "select",
559
+ {
560
+ style: selectStyle,
561
+ value: form.type,
562
+ onChange: (e) => set("type", e.target.value),
563
+ children: [
564
+ /* @__PURE__ */ jsx("option", { value: "string", children: "string" }),
565
+ /* @__PURE__ */ jsx("option", { value: "number", children: "number" }),
566
+ /* @__PURE__ */ jsx("option", { value: "boolean", children: "boolean" }),
567
+ /* @__PURE__ */ jsx("option", { value: "object", children: "object" })
568
+ ]
569
+ }
570
+ ),
504
571
  /* @__PURE__ */ jsxs("label", { style: checkboxRowStyle, children: [
505
572
  /* @__PURE__ */ jsx(
506
573
  "input",
@@ -594,7 +661,8 @@ var emptyStyle = {
594
661
  };
595
662
  var codeStyle = {
596
663
  fontFamily: "monospace",
597
- background: "#f3f4f6",
664
+ background: "#f97316",
665
+ color: "#070714",
598
666
  borderRadius: 3,
599
667
  padding: "1px 3px"
600
668
  };
@@ -2025,6 +2093,7 @@ function PreviewPanel({ store, schema }) {
2025
2093
  ] });
2026
2094
  }
2027
2095
  return /* @__PURE__ */ jsxs("div", { style: styles6.panel, children: [
2096
+ /* @__PURE__ */ jsx(DevPanel, { store }),
2028
2097
  /* @__PURE__ */ jsx("div", { style: styles6.leftCol, children: /* @__PURE__ */ jsx(
2029
2098
  StepList,
2030
2099
  {
@@ -2841,7 +2910,7 @@ var styles8 = {
2841
2910
  borderRadius: 4
2842
2911
  }
2843
2912
  };
2844
- function Toolbar({ onSave, previewMode, onTest }) {
2913
+ function Toolbar({ onSave, previewMode, onTest, isMobile }) {
2845
2914
  const { schema, isDirty, resetSchema } = useBuilderStore();
2846
2915
  const handleExport = () => {
2847
2916
  const json = JSON.stringify(schema, null, 2);
@@ -2899,12 +2968,15 @@ ${result.errors.map((e2) => `\u2022 ${e2}`).join("\n")}`);
2899
2968
  }
2900
2969
  return /* @__PURE__ */ jsxs("div", { style: styles9.toolbar, children: [
2901
2970
  /* @__PURE__ */ jsxs("div", { style: styles9.left, children: [
2902
- /* @__PURE__ */ jsx("span", { style: styles9.logo, children: "\u25C8 waypoint" }),
2903
- /* @__PURE__ */ jsx("span", { style: styles9.separator, children: "/" }),
2971
+ !isMobile && /* @__PURE__ */ jsx("span", { style: styles9.logo, children: "\u25C8 waypoint" }),
2972
+ !isMobile && /* @__PURE__ */ jsx("span", { style: styles9.separator, children: "/" }),
2904
2973
  /* @__PURE__ */ jsx(
2905
2974
  "input",
2906
2975
  {
2907
- style: styles9.journeyName,
2976
+ style: {
2977
+ ...styles9.journeyName,
2978
+ ...isMobile ? { maxWidth: 120, fontSize: 12 } : {}
2979
+ },
2908
2980
  value: schema.name,
2909
2981
  placeholder: "Journey name",
2910
2982
  onChange: (e) => useBuilderStore.setState((s) => ({
@@ -2916,25 +2988,27 @@ ${result.errors.map((e2) => `\u2022 ${e2}`).join("\n")}`);
2916
2988
  isDirty && /* @__PURE__ */ jsx("span", { style: styles9.dirtyDot, title: "Unsaved changes" })
2917
2989
  ] }),
2918
2990
  /* @__PURE__ */ jsxs("div", { style: styles9.right, children: [
2919
- onTest && /* @__PURE__ */ jsx("button", { style: { ...styles9.btn, ...styles9.testBtn }, onClick: onTest, children: "\u25B6 Tester" }),
2920
- /* @__PURE__ */ jsx("button", { style: styles9.btn, onClick: handleImport, children: "Import" }),
2921
- /* @__PURE__ */ jsx("button", { style: styles9.btn, onClick: handleExport, children: "Export JSON" }),
2991
+ onTest && /* @__PURE__ */ jsx("button", { style: { ...styles9.btn, ...styles9.testBtn }, onClick: onTest, title: "Tester", children: isMobile ? "\u25B6" : "\u25B6 Tester" }),
2992
+ /* @__PURE__ */ jsx("button", { style: styles9.btn, onClick: handleImport, title: "Import", children: isMobile ? "\u2193" : "Import" }),
2993
+ /* @__PURE__ */ jsx("button", { style: styles9.btn, onClick: handleExport, title: "Export JSON", children: isMobile ? "\u2191" : "Export JSON" }),
2922
2994
  onSave && /* @__PURE__ */ jsx(
2923
2995
  "button",
2924
2996
  {
2925
2997
  style: { ...styles9.btn, ...styles9.saveBtn },
2926
2998
  onClick: () => onSave(schema),
2927
- children: "Save"
2999
+ title: "Save",
3000
+ children: isMobile ? "\u2713" : "Save"
2928
3001
  }
2929
3002
  ),
2930
3003
  /* @__PURE__ */ jsx(
2931
3004
  "button",
2932
3005
  {
2933
3006
  style: { ...styles9.btn, color: "var(--wp-danger)" },
3007
+ title: "Reset",
2934
3008
  onClick: () => {
2935
3009
  if (confirm("Reset the journey? All changes will be lost.")) resetSchema();
2936
3010
  },
2937
- children: "Reset"
3011
+ children: isMobile ? "\u27F3" : "Reset"
2938
3012
  }
2939
3013
  )
2940
3014
  ] })
@@ -2993,18 +3067,32 @@ function WaypointBuilder({
2993
3067
  className,
2994
3068
  style
2995
3069
  }) {
2996
- const { loadSchema, schema } = useBuilderStore();
3070
+ const { loadSchema, schema, selectedStepId, selectedFieldId } = useBuilderStore();
2997
3071
  const [previewMode, setPreviewMode] = useState(false);
3072
+ const [isMobile, setIsMobile] = useState(false);
3073
+ const [activeTab, setActiveTab] = useState("steps");
2998
3074
  const previewStoreRef = useRef(null);
2999
3075
  if (previewStoreRef.current === null) {
3000
3076
  previewStoreRef.current = createRuntimeStore();
3001
3077
  }
3078
+ useEffect(() => {
3079
+ const check = () => setIsMobile(window.innerWidth < 640);
3080
+ check();
3081
+ window.addEventListener("resize", check);
3082
+ return () => window.removeEventListener("resize", check);
3083
+ }, []);
3002
3084
  useEffect(() => {
3003
3085
  if (defaultValue) loadSchema(defaultValue);
3004
3086
  }, []);
3005
3087
  useEffect(() => {
3006
3088
  onChange?.(schema);
3007
3089
  }, [schema, onChange]);
3090
+ useEffect(() => {
3091
+ if (isMobile && selectedStepId) setActiveTab("fields");
3092
+ }, [selectedStepId]);
3093
+ useEffect(() => {
3094
+ if (isMobile && selectedFieldId) setActiveTab("config");
3095
+ }, [selectedFieldId]);
3008
3096
  function handleTest() {
3009
3097
  previewStoreRef.current.getState().init(schema);
3010
3098
  setPreviewMode(true);
@@ -3014,6 +3102,7 @@ function WaypointBuilder({
3014
3102
  /* @__PURE__ */ jsx(
3015
3103
  Toolbar,
3016
3104
  {
3105
+ isMobile,
3017
3106
  onSave: !previewMode && onSave ? () => onSave(schema) : void 0,
3018
3107
  previewMode,
3019
3108
  onTest: previewMode ? () => setPreviewMode(false) : handleTest
@@ -3026,7 +3115,29 @@ function WaypointBuilder({
3026
3115
  schema,
3027
3116
  onEdit: () => setPreviewMode(false)
3028
3117
  }
3029
- ) : /* @__PURE__ */ jsxs("div", { style: layoutStyle, children: [
3118
+ ) : isMobile ? /* @__PURE__ */ jsxs(Fragment, { children: [
3119
+ /* @__PURE__ */ jsxs("div", { style: { ...colStyle, display: activeTab === "steps" ? "flex" : "none" }, children: [
3120
+ /* @__PURE__ */ jsx("div", { style: { flex: 1, overflow: "hidden", display: "flex", flexDirection: "column" }, children: /* @__PURE__ */ jsx(StepList2, {}) }),
3121
+ /* @__PURE__ */ jsx("div", { style: { borderTop: "1px solid var(--wp-border)", flexShrink: 0, overflow: "auto", maxHeight: 200 }, children: /* @__PURE__ */ jsx(ExternalVariablePanel, {}) })
3122
+ ] }),
3123
+ /* @__PURE__ */ jsx("div", { style: { ...colStyle, display: activeTab === "fields" ? "flex" : "none" }, children: /* @__PURE__ */ jsx(FieldList, {}) }),
3124
+ /* @__PURE__ */ jsxs("div", { style: { ...colStyle, display: activeTab === "config" ? "flex" : "none" }, children: [
3125
+ /* @__PURE__ */ jsx("div", { style: { flex: 1, borderBottom: "1px solid var(--wp-border)", overflow: "hidden" }, children: /* @__PURE__ */ jsx(StepEditor, {}) }),
3126
+ /* @__PURE__ */ jsx("div", { style: { flex: 1, overflow: "hidden" }, children: /* @__PURE__ */ jsx(FieldEditor, {}) })
3127
+ ] }),
3128
+ /* @__PURE__ */ jsx("div", { style: tabBarStyle, children: ["steps", "fields", "config"].map((tab) => /* @__PURE__ */ jsxs(
3129
+ "button",
3130
+ {
3131
+ style: { ...tabBtnStyle, ...activeTab === tab ? tabBtnActiveStyle : {} },
3132
+ onClick: () => setActiveTab(tab),
3133
+ children: [
3134
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 14 }, children: tab === "steps" ? "\u26A1" : tab === "fields" ? "\u229E" : "\u2699" }),
3135
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 11, fontWeight: 600, textTransform: "capitalize" }, children: tab })
3136
+ ]
3137
+ },
3138
+ tab
3139
+ )) })
3140
+ ] }) : /* @__PURE__ */ jsxs("div", { style: layoutStyle, children: [
3030
3141
  /* @__PURE__ */ jsxs("div", { style: colStyle, children: [
3031
3142
  /* @__PURE__ */ jsx("div", { style: { flex: 1, overflow: "hidden", display: "flex", flexDirection: "column" }, children: /* @__PURE__ */ jsx(StepList2, {}) }),
3032
3143
  /* @__PURE__ */ jsx("div", { style: { borderTop: "1px solid var(--wp-border)", flexShrink: 0, overflow: "auto", maxHeight: 280 }, children: /* @__PURE__ */ jsx(ExternalVariablePanel, {}) })
@@ -3068,6 +3179,29 @@ var dividerStyle = {
3068
3179
  background: "var(--wp-border)",
3069
3180
  flexShrink: 0
3070
3181
  };
3182
+ var tabBarStyle = {
3183
+ display: "flex",
3184
+ borderTop: "1px solid var(--wp-border)",
3185
+ background: "var(--wp-toolbar-bg)",
3186
+ flexShrink: 0
3187
+ };
3188
+ var tabBtnStyle = {
3189
+ flex: 1,
3190
+ display: "flex",
3191
+ flexDirection: "column",
3192
+ alignItems: "center",
3193
+ justifyContent: "center",
3194
+ gap: 3,
3195
+ padding: "8px 4px",
3196
+ border: "none",
3197
+ background: "transparent",
3198
+ color: "var(--wp-text-subtle)",
3199
+ cursor: "pointer"
3200
+ };
3201
+ var tabBtnActiveStyle = {
3202
+ color: "var(--wp-primary)",
3203
+ borderTop: "2px solid var(--wp-primary)"
3204
+ };
3071
3205
 
3072
3206
  export { DARK_THEME, DEFAULT_THEME, WaypointBuilder, buildThemeVars, useBuilderStore };
3073
3207
  //# sourceMappingURL=index.js.map