@toriistudio/v0-playground 0.2.7 → 0.2.8

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.mts CHANGED
@@ -5,37 +5,45 @@ declare function Playground({ children }: {
5
5
  children: ReactNode;
6
6
  }): react_jsx_runtime.JSX.Element | null;
7
7
 
8
- type ControlType = {
8
+ type BaseControl = {
9
+ hidden?: boolean;
10
+ };
11
+ type ControlType = ({
9
12
  type: "boolean";
10
13
  value: boolean;
11
- } | {
14
+ } & BaseControl) | ({
12
15
  type: "number";
13
16
  value: number;
14
17
  min?: number;
15
18
  max?: number;
16
19
  step?: number;
17
- } | {
20
+ } & BaseControl) | ({
18
21
  type: "string";
19
22
  value: string;
20
- } | {
23
+ } & BaseControl) | ({
21
24
  type: "color";
22
25
  value: string;
23
- } | {
26
+ } & BaseControl) | ({
24
27
  type: "select";
25
28
  value: string;
26
29
  options: string[];
27
- } | {
30
+ } & BaseControl) | ({
28
31
  type: "button";
29
32
  onClick?: () => void;
30
33
  label?: string;
31
34
  render?: () => React.ReactNode;
32
- };
35
+ } & BaseControl);
33
36
  type ControlsSchema = Record<string, ControlType>;
37
+ type ControlsConfig = {
38
+ showCopyButton?: boolean;
39
+ mainLabel?: string;
40
+ };
34
41
  declare const ControlsProvider: ({ children }: {
35
42
  children: ReactNode;
36
43
  }) => react_jsx_runtime.JSX.Element;
37
44
  declare const useControls: <T extends ControlsSchema>(schema: T, options?: {
38
45
  componentName?: string;
46
+ config?: ControlsConfig;
39
47
  }) => { [K in keyof T]: T[K] extends {
40
48
  value: infer V;
41
49
  } ? V : never; } & {
@@ -46,6 +54,7 @@ declare const useControls: <T extends ControlsSchema>(schema: T, options?: {
46
54
  };
47
55
  declare const useUrlSyncedControls: <T extends ControlsSchema>(schema: T, options?: {
48
56
  componentName?: string;
57
+ config?: ControlsConfig;
49
58
  }) => { [K in keyof T]: T[K] extends {
50
59
  value: infer V;
51
60
  } ? V : never; } & {
package/dist/index.d.ts CHANGED
@@ -5,37 +5,45 @@ declare function Playground({ children }: {
5
5
  children: ReactNode;
6
6
  }): react_jsx_runtime.JSX.Element | null;
7
7
 
8
- type ControlType = {
8
+ type BaseControl = {
9
+ hidden?: boolean;
10
+ };
11
+ type ControlType = ({
9
12
  type: "boolean";
10
13
  value: boolean;
11
- } | {
14
+ } & BaseControl) | ({
12
15
  type: "number";
13
16
  value: number;
14
17
  min?: number;
15
18
  max?: number;
16
19
  step?: number;
17
- } | {
20
+ } & BaseControl) | ({
18
21
  type: "string";
19
22
  value: string;
20
- } | {
23
+ } & BaseControl) | ({
21
24
  type: "color";
22
25
  value: string;
23
- } | {
26
+ } & BaseControl) | ({
24
27
  type: "select";
25
28
  value: string;
26
29
  options: string[];
27
- } | {
30
+ } & BaseControl) | ({
28
31
  type: "button";
29
32
  onClick?: () => void;
30
33
  label?: string;
31
34
  render?: () => React.ReactNode;
32
- };
35
+ } & BaseControl);
33
36
  type ControlsSchema = Record<string, ControlType>;
37
+ type ControlsConfig = {
38
+ showCopyButton?: boolean;
39
+ mainLabel?: string;
40
+ };
34
41
  declare const ControlsProvider: ({ children }: {
35
42
  children: ReactNode;
36
43
  }) => react_jsx_runtime.JSX.Element;
37
44
  declare const useControls: <T extends ControlsSchema>(schema: T, options?: {
38
45
  componentName?: string;
46
+ config?: ControlsConfig;
39
47
  }) => { [K in keyof T]: T[K] extends {
40
48
  value: infer V;
41
49
  } ? V : never; } & {
@@ -46,6 +54,7 @@ declare const useControls: <T extends ControlsSchema>(schema: T, options?: {
46
54
  };
47
55
  declare const useUrlSyncedControls: <T extends ControlsSchema>(schema: T, options?: {
48
56
  componentName?: string;
57
+ config?: ControlsConfig;
49
58
  }) => { [K in keyof T]: T[K] extends {
50
59
  value: infer V;
51
60
  } ? V : never; } & {
package/dist/index.js CHANGED
@@ -166,6 +166,9 @@ var useControlsContext = () => {
166
166
  var ControlsProvider = ({ children }) => {
167
167
  const [schema, setSchema] = (0, import_react2.useState)({});
168
168
  const [values, setValues] = (0, import_react2.useState)({});
169
+ const [config, setConfig] = (0, import_react2.useState)({
170
+ showCopyButton: true
171
+ });
169
172
  const [componentName, setComponentName] = (0, import_react2.useState)();
170
173
  const setValue = (key, value) => {
171
174
  setValues((prev) => ({ ...prev, [key]: value }));
@@ -174,12 +177,18 @@ var ControlsProvider = ({ children }) => {
174
177
  if (opts?.componentName) {
175
178
  setComponentName(opts.componentName);
176
179
  }
180
+ if (opts?.config) {
181
+ setConfig((prev) => ({
182
+ ...prev,
183
+ ...opts.config
184
+ }));
185
+ }
177
186
  setSchema((prevSchema) => ({ ...prevSchema, ...newSchema }));
178
187
  setValues((prevValues) => {
179
188
  const updated = { ...prevValues };
180
189
  for (const key in newSchema) {
190
+ const control = newSchema[key];
181
191
  if (!(key in updated)) {
182
- const control = newSchema[key];
183
192
  if ("value" in control) {
184
193
  updated[key] = control.value;
185
194
  }
@@ -189,8 +198,15 @@ var ControlsProvider = ({ children }) => {
189
198
  });
190
199
  };
191
200
  const contextValue = (0, import_react2.useMemo)(
192
- () => ({ schema, values, setValue, registerSchema, componentName }),
193
- [schema, values, componentName]
201
+ () => ({
202
+ schema,
203
+ values,
204
+ setValue,
205
+ registerSchema,
206
+ componentName,
207
+ config
208
+ }),
209
+ [schema, values, componentName, config]
194
210
  );
195
211
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ControlsContext.Provider, { value: contextValue, children });
196
212
  };
@@ -551,13 +567,13 @@ var import_jsx_runtime10 = require("react/jsx-runtime");
551
567
  var ControlPanel = () => {
552
568
  const [copied, setCopied] = (0, import_react5.useState)(false);
553
569
  const { leftPanelWidth, isDesktop, isHydrated, sidebarNarrow } = useResizableLayout();
554
- const { schema, setValue, values, componentName } = useControlsContext();
570
+ const { schema, setValue, values, componentName, config } = useControlsContext();
555
571
  const previewUrl = usePreviewUrl(values);
556
572
  const normalControls = Object.entries(schema).filter(
557
- ([, control]) => control.type !== "button"
573
+ ([, control]) => control.type !== "button" && !control.hidden
558
574
  );
559
575
  const buttonControls = Object.entries(schema).filter(
560
- ([, control]) => control.type === "button"
576
+ ([, control]) => control.type === "button" && !control.hidden
561
577
  );
562
578
  const jsx12 = (0, import_react5.useMemo)(() => {
563
579
  if (!componentName) return "";
@@ -588,7 +604,7 @@ var ControlPanel = () => {
588
604
  } : {}
589
605
  },
590
606
  children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "mb-10 space-y-4 p-2 md:p-4 border border-stone-700 rounded-md", children: [
591
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "space-y-1", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { className: "text-lg text-stone-100 font-bold", children: "Controls" }) }),
607
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "space-y-1", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { className: "text-lg text-stone-100 font-bold", children: config?.mainLabel ?? "Controls" }) }),
592
608
  /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "space-y-4 pt-2", children: [
593
609
  normalControls.map(([key, control]) => {
594
610
  const value = values[key];
@@ -685,43 +701,49 @@ var ControlPanel = () => {
685
701
  return null;
686
702
  }
687
703
  }),
688
- (buttonControls.length > 0 || jsx12) && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "border-t border-stone-700", children: [
689
- jsx12 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex-1 pt-4", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
690
- "button",
691
- {
692
- onClick: () => {
693
- navigator.clipboard.writeText(jsx12);
694
- setCopied(true);
695
- setTimeout(() => setCopied(false), 5e3);
696
- },
697
- className: "w-full px-4 py-2 text-sm bg-stone-700 hover:bg-stone-600 text-white rounded flex items-center justify-center gap-2",
698
- children: copied ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
699
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.Check, { className: "w-4 h-4" }),
700
- "Copied"
701
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
702
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.Copy, { className: "w-4 h-4" }),
703
- "Copy to Clipboard"
704
- ] })
705
- }
706
- ) }, "control-panel-jsx"),
707
- buttonControls.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex flex-wrap gap-2 pt-4", children: buttonControls.map(
708
- ([key, control]) => control.type === "button" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
709
- "div",
710
- {
711
- className: "flex-1",
712
- children: control.render ? control.render() : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
713
- "button",
704
+ (buttonControls.length > 0 || jsx12) && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
705
+ "div",
706
+ {
707
+ className: `${normalControls.length > 0 ? "border-t" : ""} border-stone-700`,
708
+ children: [
709
+ jsx12 && config?.showCopyButton !== false && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex-1 pt-4", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
710
+ "button",
711
+ {
712
+ onClick: () => {
713
+ navigator.clipboard.writeText(jsx12);
714
+ setCopied(true);
715
+ setTimeout(() => setCopied(false), 5e3);
716
+ },
717
+ className: "w-full px-4 py-2 text-sm bg-stone-700 hover:bg-stone-600 text-white rounded flex items-center justify-center gap-2",
718
+ children: copied ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
719
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.Check, { className: "w-4 h-4" }),
720
+ "Copied"
721
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
722
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.Copy, { className: "w-4 h-4" }),
723
+ "Copy to Clipboard"
724
+ ] })
725
+ }
726
+ ) }, "control-panel-jsx"),
727
+ buttonControls.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex flex-wrap gap-2 pt-4", children: buttonControls.map(
728
+ ([key, control]) => control.type === "button" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
729
+ "div",
714
730
  {
715
- onClick: control.onClick,
716
- className: "w-full px-4 py-2 text-sm bg-stone-700 hover:bg-stone-600 text-white rounded",
717
- children: control.label ?? key
718
- }
719
- )
720
- },
721
- `control-panel-custom-${key}`
722
- ) : null
723
- ) })
724
- ] })
731
+ className: "flex-1",
732
+ children: control.render ? control.render() : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
733
+ "button",
734
+ {
735
+ onClick: control.onClick,
736
+ className: "w-full px-4 py-2 text-sm bg-stone-700 hover:bg-stone-600 text-white rounded",
737
+ children: control.label ?? key
738
+ }
739
+ )
740
+ },
741
+ `control-panel-custom-${key}`
742
+ ) : null
743
+ ) })
744
+ ]
745
+ }
746
+ )
725
747
  ] }),
726
748
  previewUrl && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Button, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
727
749
  "a",
package/dist/index.mjs CHANGED
@@ -140,6 +140,9 @@ var useControlsContext = () => {
140
140
  var ControlsProvider = ({ children }) => {
141
141
  const [schema, setSchema] = useState2({});
142
142
  const [values, setValues] = useState2({});
143
+ const [config, setConfig] = useState2({
144
+ showCopyButton: true
145
+ });
143
146
  const [componentName, setComponentName] = useState2();
144
147
  const setValue = (key, value) => {
145
148
  setValues((prev) => ({ ...prev, [key]: value }));
@@ -148,12 +151,18 @@ var ControlsProvider = ({ children }) => {
148
151
  if (opts?.componentName) {
149
152
  setComponentName(opts.componentName);
150
153
  }
154
+ if (opts?.config) {
155
+ setConfig((prev) => ({
156
+ ...prev,
157
+ ...opts.config
158
+ }));
159
+ }
151
160
  setSchema((prevSchema) => ({ ...prevSchema, ...newSchema }));
152
161
  setValues((prevValues) => {
153
162
  const updated = { ...prevValues };
154
163
  for (const key in newSchema) {
164
+ const control = newSchema[key];
155
165
  if (!(key in updated)) {
156
- const control = newSchema[key];
157
166
  if ("value" in control) {
158
167
  updated[key] = control.value;
159
168
  }
@@ -163,8 +172,15 @@ var ControlsProvider = ({ children }) => {
163
172
  });
164
173
  };
165
174
  const contextValue = useMemo(
166
- () => ({ schema, values, setValue, registerSchema, componentName }),
167
- [schema, values, componentName]
175
+ () => ({
176
+ schema,
177
+ values,
178
+ setValue,
179
+ registerSchema,
180
+ componentName,
181
+ config
182
+ }),
183
+ [schema, values, componentName, config]
168
184
  );
169
185
  return /* @__PURE__ */ jsx2(ControlsContext.Provider, { value: contextValue, children });
170
186
  };
@@ -525,13 +541,13 @@ import { Fragment, jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
525
541
  var ControlPanel = () => {
526
542
  const [copied, setCopied] = useState4(false);
527
543
  const { leftPanelWidth, isDesktop, isHydrated, sidebarNarrow } = useResizableLayout();
528
- const { schema, setValue, values, componentName } = useControlsContext();
544
+ const { schema, setValue, values, componentName, config } = useControlsContext();
529
545
  const previewUrl = usePreviewUrl(values);
530
546
  const normalControls = Object.entries(schema).filter(
531
- ([, control]) => control.type !== "button"
547
+ ([, control]) => control.type !== "button" && !control.hidden
532
548
  );
533
549
  const buttonControls = Object.entries(schema).filter(
534
- ([, control]) => control.type === "button"
550
+ ([, control]) => control.type === "button" && !control.hidden
535
551
  );
536
552
  const jsx12 = useMemo2(() => {
537
553
  if (!componentName) return "";
@@ -562,7 +578,7 @@ var ControlPanel = () => {
562
578
  } : {}
563
579
  },
564
580
  children: /* @__PURE__ */ jsxs4("div", { className: "mb-10 space-y-4 p-2 md:p-4 border border-stone-700 rounded-md", children: [
565
- /* @__PURE__ */ jsx10("div", { className: "space-y-1", children: /* @__PURE__ */ jsx10("h1", { className: "text-lg text-stone-100 font-bold", children: "Controls" }) }),
581
+ /* @__PURE__ */ jsx10("div", { className: "space-y-1", children: /* @__PURE__ */ jsx10("h1", { className: "text-lg text-stone-100 font-bold", children: config?.mainLabel ?? "Controls" }) }),
566
582
  /* @__PURE__ */ jsxs4("div", { className: "space-y-4 pt-2", children: [
567
583
  normalControls.map(([key, control]) => {
568
584
  const value = values[key];
@@ -659,43 +675,49 @@ var ControlPanel = () => {
659
675
  return null;
660
676
  }
661
677
  }),
662
- (buttonControls.length > 0 || jsx12) && /* @__PURE__ */ jsxs4("div", { className: "border-t border-stone-700", children: [
663
- jsx12 && /* @__PURE__ */ jsx10("div", { className: "flex-1 pt-4", children: /* @__PURE__ */ jsx10(
664
- "button",
665
- {
666
- onClick: () => {
667
- navigator.clipboard.writeText(jsx12);
668
- setCopied(true);
669
- setTimeout(() => setCopied(false), 5e3);
670
- },
671
- className: "w-full px-4 py-2 text-sm bg-stone-700 hover:bg-stone-600 text-white rounded flex items-center justify-center gap-2",
672
- children: copied ? /* @__PURE__ */ jsxs4(Fragment, { children: [
673
- /* @__PURE__ */ jsx10(Check2, { className: "w-4 h-4" }),
674
- "Copied"
675
- ] }) : /* @__PURE__ */ jsxs4(Fragment, { children: [
676
- /* @__PURE__ */ jsx10(Copy, { className: "w-4 h-4" }),
677
- "Copy to Clipboard"
678
- ] })
679
- }
680
- ) }, "control-panel-jsx"),
681
- buttonControls.length > 0 && /* @__PURE__ */ jsx10("div", { className: "flex flex-wrap gap-2 pt-4", children: buttonControls.map(
682
- ([key, control]) => control.type === "button" ? /* @__PURE__ */ jsx10(
683
- "div",
684
- {
685
- className: "flex-1",
686
- children: control.render ? control.render() : /* @__PURE__ */ jsx10(
687
- "button",
678
+ (buttonControls.length > 0 || jsx12) && /* @__PURE__ */ jsxs4(
679
+ "div",
680
+ {
681
+ className: `${normalControls.length > 0 ? "border-t" : ""} border-stone-700`,
682
+ children: [
683
+ jsx12 && config?.showCopyButton !== false && /* @__PURE__ */ jsx10("div", { className: "flex-1 pt-4", children: /* @__PURE__ */ jsx10(
684
+ "button",
685
+ {
686
+ onClick: () => {
687
+ navigator.clipboard.writeText(jsx12);
688
+ setCopied(true);
689
+ setTimeout(() => setCopied(false), 5e3);
690
+ },
691
+ className: "w-full px-4 py-2 text-sm bg-stone-700 hover:bg-stone-600 text-white rounded flex items-center justify-center gap-2",
692
+ children: copied ? /* @__PURE__ */ jsxs4(Fragment, { children: [
693
+ /* @__PURE__ */ jsx10(Check2, { className: "w-4 h-4" }),
694
+ "Copied"
695
+ ] }) : /* @__PURE__ */ jsxs4(Fragment, { children: [
696
+ /* @__PURE__ */ jsx10(Copy, { className: "w-4 h-4" }),
697
+ "Copy to Clipboard"
698
+ ] })
699
+ }
700
+ ) }, "control-panel-jsx"),
701
+ buttonControls.length > 0 && /* @__PURE__ */ jsx10("div", { className: "flex flex-wrap gap-2 pt-4", children: buttonControls.map(
702
+ ([key, control]) => control.type === "button" ? /* @__PURE__ */ jsx10(
703
+ "div",
688
704
  {
689
- onClick: control.onClick,
690
- className: "w-full px-4 py-2 text-sm bg-stone-700 hover:bg-stone-600 text-white rounded",
691
- children: control.label ?? key
692
- }
693
- )
694
- },
695
- `control-panel-custom-${key}`
696
- ) : null
697
- ) })
698
- ] })
705
+ className: "flex-1",
706
+ children: control.render ? control.render() : /* @__PURE__ */ jsx10(
707
+ "button",
708
+ {
709
+ onClick: control.onClick,
710
+ className: "w-full px-4 py-2 text-sm bg-stone-700 hover:bg-stone-600 text-white rounded",
711
+ children: control.label ?? key
712
+ }
713
+ )
714
+ },
715
+ `control-panel-custom-${key}`
716
+ ) : null
717
+ ) })
718
+ ]
719
+ }
720
+ )
699
721
  ] }),
700
722
  previewUrl && /* @__PURE__ */ jsx10(Button, { asChild: true, children: /* @__PURE__ */ jsxs4(
701
723
  "a",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toriistudio/v0-playground",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "V0 Playground",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -30,7 +30,9 @@
30
30
  "scripts": {
31
31
  "build": "tsup",
32
32
  "local:push": "yarn build && yalc push",
33
- "prepublishOnly": "npm run build",
33
+ "release:patch": "npm version patch && git push --follow-tags && npm publish",
34
+ "release:minor": "npm version minor && git push --follow-tags && npm publish",
35
+ "release:major": "npm version major && git push --follow-tags && npm publish",
34
36
  "test": "echo \"Error: no test specified\" && exit 1"
35
37
  },
36
38
  "repository": {