@farcaster/snap 2.0.0 → 2.0.1
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/colors.d.ts +4 -4
- package/dist/colors.js +20 -20
- package/dist/constants.d.ts +17 -1
- package/dist/constants.js +19 -1
- package/dist/index.d.ts +4 -6
- package/dist/index.js +2 -4
- package/dist/react/accent-context.d.ts +3 -1
- package/dist/react/accent-context.js +7 -4
- package/dist/react/catalog-renderer.js +4 -0
- package/dist/react/components/action-button.d.ts +2 -1
- package/dist/react/components/action-button.js +32 -13
- package/dist/react/components/badge.js +8 -8
- package/dist/react/components/bar-chart.d.ts +5 -0
- package/dist/react/components/bar-chart.js +26 -0
- package/dist/react/components/cell-grid.d.ts +5 -0
- package/dist/react/components/cell-grid.js +87 -0
- package/dist/react/components/icon.js +4 -10
- package/dist/react/components/input.js +12 -6
- package/dist/react/components/item-group.js +3 -1
- package/dist/react/components/item.d.ts +3 -3
- package/dist/react/components/item.js +4 -3
- package/dist/react/components/progress.js +3 -3
- package/dist/react/components/separator.js +3 -1
- package/dist/react/components/slider.js +15 -10
- package/dist/react/components/switch.js +10 -12
- package/dist/react/components/text.js +6 -14
- package/dist/react/components/toggle-group.js +20 -6
- package/dist/react/hooks/use-snap-colors.d.ts +38 -0
- package/dist/react/hooks/use-snap-colors.js +81 -0
- package/dist/react/index.d.ts +13 -1
- package/dist/react/index.js +9 -188
- package/dist/react/snap-view-core.d.ts +11 -0
- package/dist/react/snap-view-core.js +224 -0
- package/dist/react/v1/snap-view.d.ts +16 -0
- package/dist/react/v1/snap-view.js +90 -0
- package/dist/react/v2/snap-view.d.ts +23 -0
- package/dist/react/v2/snap-view.js +91 -0
- package/dist/react-native/catalog-renderer.d.ts +5 -0
- package/dist/react-native/catalog-renderer.js +40 -0
- package/dist/react-native/components/snap-action-button.d.ts +2 -0
- package/dist/react-native/components/snap-action-button.js +69 -0
- package/dist/react-native/components/snap-badge.d.ts +2 -0
- package/dist/react-native/components/snap-badge.js +41 -0
- package/dist/react-native/components/snap-bar-chart.d.ts +2 -0
- package/dist/react-native/components/snap-bar-chart.js +39 -0
- package/dist/react-native/components/snap-cell-grid.d.ts +2 -0
- package/dist/react-native/components/snap-cell-grid.js +94 -0
- package/dist/react-native/components/snap-icon.d.ts +5 -0
- package/dist/react-native/components/snap-icon.js +56 -0
- package/dist/react-native/components/snap-image.d.ts +2 -0
- package/dist/react-native/components/snap-image.js +23 -0
- package/dist/react-native/components/snap-input.d.ts +2 -0
- package/dist/react-native/components/snap-input.js +37 -0
- package/dist/react-native/components/snap-item-group.d.ts +5 -0
- package/dist/react-native/components/snap-item-group.js +23 -0
- package/dist/react-native/components/snap-item.d.ts +5 -0
- package/dist/react-native/components/snap-item.js +42 -0
- package/dist/react-native/components/snap-progress.d.ts +2 -0
- package/dist/react-native/components/snap-progress.js +26 -0
- package/dist/react-native/components/snap-separator.d.ts +2 -0
- package/dist/react-native/components/snap-separator.js +23 -0
- package/dist/react-native/components/snap-slider.d.ts +2 -0
- package/dist/react-native/components/snap-slider.js +43 -0
- package/dist/react-native/components/snap-stack.d.ts +5 -0
- package/dist/react-native/components/snap-stack.js +49 -0
- package/dist/react-native/components/snap-switch.d.ts +2 -0
- package/dist/react-native/components/snap-switch.js +31 -0
- package/dist/react-native/components/snap-text.d.ts +2 -0
- package/dist/react-native/components/snap-text.js +35 -0
- package/dist/react-native/components/snap-toggle-group.d.ts +2 -0
- package/dist/react-native/components/snap-toggle-group.js +99 -0
- package/dist/react-native/confetti-overlay.d.ts +1 -0
- package/dist/react-native/confetti-overlay.js +106 -0
- package/dist/react-native/index.d.ts +28 -0
- package/dist/react-native/index.js +15 -0
- package/dist/react-native/snap-view-core.d.ts +11 -0
- package/dist/react-native/snap-view-core.js +153 -0
- package/dist/react-native/theme.d.ts +27 -0
- package/dist/react-native/theme.js +43 -0
- package/dist/react-native/types.d.ts +42 -0
- package/dist/react-native/types.js +1 -0
- package/dist/react-native/use-snap-palette.d.ts +13 -0
- package/dist/react-native/use-snap-palette.js +48 -0
- package/dist/react-native/v1/snap-view.d.ts +24 -0
- package/dist/react-native/v1/snap-view.js +96 -0
- package/dist/react-native/v2/snap-view.d.ts +33 -0
- package/dist/react-native/v2/snap-view.js +114 -0
- package/dist/schemas.d.ts +100 -13
- package/dist/schemas.js +28 -10
- package/dist/server/parseRequest.d.ts +10 -0
- package/dist/server/parseRequest.js +48 -7
- package/dist/server/verify.d.ts +1 -0
- package/dist/server/verify.js +1 -0
- package/dist/ui/badge.d.ts +7 -2
- package/dist/ui/badge.js +2 -0
- package/dist/ui/bar-chart.d.ts +30 -0
- package/dist/ui/bar-chart.js +30 -0
- package/dist/ui/button.d.ts +4 -6
- package/dist/ui/button.js +1 -1
- package/dist/ui/catalog.d.ts +90 -16
- package/dist/ui/catalog.js +17 -3
- package/dist/ui/cell-grid.d.ts +34 -0
- package/dist/ui/cell-grid.js +39 -0
- package/dist/ui/icon.d.ts +2 -2
- package/dist/ui/image.d.ts +1 -2
- package/dist/ui/image.js +1 -1
- package/dist/ui/index.d.ts +4 -0
- package/dist/ui/index.js +2 -0
- package/dist/ui/item.d.ts +1 -3
- package/dist/ui/item.js +1 -1
- package/dist/ui/schema.d.ts +6 -2
- package/dist/ui/schema.js +2 -2
- package/dist/ui/slider.d.ts +1 -0
- package/dist/ui/slider.js +2 -0
- package/dist/ui/text.d.ts +2 -4
- package/dist/ui/text.js +2 -2
- package/dist/validator.d.ts +3 -2
- package/dist/validator.js +198 -2
- package/llms.txt +199 -0
- package/package.json +9 -3
- package/src/colors.ts +20 -20
- package/src/constants.ts +23 -1
- package/src/index.ts +16 -13
- package/src/react/accent-context.tsx +13 -6
- package/src/react/catalog-renderer.tsx +4 -0
- package/src/react/components/action-button.tsx +47 -20
- package/src/react/components/badge.tsx +14 -18
- package/src/react/components/bar-chart.tsx +69 -0
- package/src/react/components/cell-grid.tsx +128 -0
- package/src/react/components/icon.tsx +5 -18
- package/src/react/components/input.tsx +20 -9
- package/src/react/components/item-group.tsx +4 -1
- package/src/react/components/item.tsx +13 -10
- package/src/react/components/progress.tsx +12 -7
- package/src/react/components/separator.tsx +8 -1
- package/src/react/components/slider.tsx +28 -15
- package/src/react/components/switch.tsx +12 -16
- package/src/react/components/text.tsx +14 -23
- package/src/react/components/toggle-group.tsx +26 -9
- package/src/react/hooks/use-snap-colors.ts +128 -0
- package/src/react/index.tsx +49 -265
- package/src/react/snap-view-core.tsx +340 -0
- package/src/react/v1/snap-view.tsx +176 -0
- package/src/react/v2/snap-view.tsx +199 -0
- package/src/react-native/catalog-renderer.tsx +41 -0
- package/src/react-native/components/snap-action-button.tsx +96 -0
- package/src/react-native/components/snap-badge.tsx +60 -0
- package/src/react-native/components/snap-bar-chart.tsx +73 -0
- package/src/react-native/components/snap-cell-grid.tsx +150 -0
- package/src/react-native/components/snap-icon.tsx +102 -0
- package/src/react-native/components/snap-image.tsx +37 -0
- package/src/react-native/components/snap-input.tsx +58 -0
- package/src/react-native/components/snap-item-group.tsx +43 -0
- package/src/react-native/components/snap-item.tsx +66 -0
- package/src/react-native/components/snap-progress.tsx +40 -0
- package/src/react-native/components/snap-separator.tsx +32 -0
- package/src/react-native/components/snap-slider.tsx +85 -0
- package/src/react-native/components/snap-stack.tsx +66 -0
- package/src/react-native/components/snap-switch.tsx +46 -0
- package/src/react-native/components/snap-text.tsx +51 -0
- package/src/react-native/components/snap-toggle-group.tsx +127 -0
- package/src/react-native/confetti-overlay.tsx +134 -0
- package/src/react-native/index.tsx +83 -0
- package/src/react-native/snap-view-core.tsx +209 -0
- package/src/react-native/theme.tsx +85 -0
- package/src/react-native/types.ts +38 -0
- package/src/react-native/use-snap-palette.ts +64 -0
- package/src/react-native/v1/snap-view.tsx +229 -0
- package/src/react-native/v2/snap-view.tsx +283 -0
- package/src/schemas.ts +68 -17
- package/src/server/parseRequest.ts +68 -9
- package/src/server/verify.ts +2 -0
- package/src/ui/README.md +8 -8
- package/src/ui/badge.ts +2 -0
- package/src/ui/bar-chart.ts +38 -0
- package/src/ui/button.ts +1 -1
- package/src/ui/catalog.ts +19 -3
- package/src/ui/cell-grid.ts +49 -0
- package/src/ui/image.ts +1 -1
- package/src/ui/index.ts +6 -0
- package/src/ui/item.ts +1 -1
- package/src/ui/schema.ts +2 -2
- package/src/ui/slider.ts +2 -0
- package/src/ui/text.ts +2 -2
- package/src/validator.ts +246 -2
- package/dist/dataStore.d.ts +0 -12
- package/dist/dataStore.js +0 -35
- package/dist/middleware.d.ts +0 -3
- package/dist/middleware.js +0 -3
- package/dist/react/hooks/use-snap-accent.d.ts +0 -13
- package/dist/react/hooks/use-snap-accent.js +0 -32
- package/src/dataStore.ts +0 -62
- package/src/middleware.ts +0 -7
- package/src/react/hooks/use-snap-accent.ts +0 -45
package/dist/colors.d.ts
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
* it to a hex value appropriate for its current light/dark mode.
|
|
4
4
|
*
|
|
5
5
|
* Light-mode hex values (used by emulator):
|
|
6
|
-
* gray=#
|
|
7
|
-
* green=#
|
|
6
|
+
* gray=#6E6A86 blue=#286983 red=#B4637A amber=#EA9D34
|
|
7
|
+
* green=#3E8F8F teal=#56949F purple=#907AA9 pink=#D7827E
|
|
8
8
|
*
|
|
9
9
|
* Dark-mode hex values (for reference; client-owned):
|
|
10
|
-
* gray=#
|
|
11
|
-
* green=#
|
|
10
|
+
* gray=#908CAA blue=#9CCFD8 red=#EB6F92 amber=#F6C177
|
|
11
|
+
* green=#56D4A4 teal=#3E8FB0 purple=#C4A7E7 pink=#EBBCBA
|
|
12
12
|
*/
|
|
13
13
|
export declare const PALETTE_COLOR: {
|
|
14
14
|
readonly gray: "gray";
|
package/dist/colors.js
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
* it to a hex value appropriate for its current light/dark mode.
|
|
4
4
|
*
|
|
5
5
|
* Light-mode hex values (used by emulator):
|
|
6
|
-
* gray=#
|
|
7
|
-
* green=#
|
|
6
|
+
* gray=#6E6A86 blue=#286983 red=#B4637A amber=#EA9D34
|
|
7
|
+
* green=#3E8F8F teal=#56949F purple=#907AA9 pink=#D7827E
|
|
8
8
|
*
|
|
9
9
|
* Dark-mode hex values (for reference; client-owned):
|
|
10
|
-
* gray=#
|
|
11
|
-
* green=#
|
|
10
|
+
* gray=#908CAA blue=#9CCFD8 red=#EB6F92 amber=#F6C177
|
|
11
|
+
* green=#56D4A4 teal=#3E8FB0 purple=#C4A7E7 pink=#EBBCBA
|
|
12
12
|
*/
|
|
13
13
|
export const PALETTE_COLOR = {
|
|
14
14
|
gray: "gray",
|
|
@@ -34,25 +34,25 @@ export const PALETTE_COLOR_VALUES = [
|
|
|
34
34
|
];
|
|
35
35
|
/** Light-mode hex for each palette color (emulator / reference client). */
|
|
36
36
|
export const PALETTE_LIGHT_HEX = {
|
|
37
|
-
gray: "#
|
|
38
|
-
blue: "#
|
|
39
|
-
red: "#
|
|
40
|
-
amber: "#
|
|
41
|
-
green: "#
|
|
42
|
-
teal: "#
|
|
43
|
-
purple: "#
|
|
44
|
-
pink: "#
|
|
37
|
+
gray: "#6E6A86",
|
|
38
|
+
blue: "#286983",
|
|
39
|
+
red: "#B4637A",
|
|
40
|
+
amber: "#EA9D34",
|
|
41
|
+
green: "#3E8F8F",
|
|
42
|
+
teal: "#56949F",
|
|
43
|
+
purple: "#907AA9",
|
|
44
|
+
pink: "#D7827E",
|
|
45
45
|
};
|
|
46
46
|
/** Dark-mode hex for each palette color (reference). */
|
|
47
47
|
export const PALETTE_DARK_HEX = {
|
|
48
|
-
gray: "#
|
|
49
|
-
blue: "#
|
|
50
|
-
red: "#
|
|
51
|
-
amber: "#
|
|
52
|
-
green: "#
|
|
53
|
-
teal: "#
|
|
54
|
-
purple: "#
|
|
55
|
-
pink: "#
|
|
48
|
+
gray: "#908CAA",
|
|
49
|
+
blue: "#9CCFD8",
|
|
50
|
+
red: "#EB6F92",
|
|
51
|
+
amber: "#F6C177",
|
|
52
|
+
green: "#56D4A4",
|
|
53
|
+
teal: "#3E8FB0",
|
|
54
|
+
purple: "#C4A7E7",
|
|
55
|
+
pink: "#EBBCBA",
|
|
56
56
|
};
|
|
57
57
|
export const PROGRESS_COLOR_VALUES = [
|
|
58
58
|
PALETTE_COLOR_ACCENT,
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const SPEC_VERSION_1: "1.0";
|
|
2
|
+
export declare const SPEC_VERSION_2: "2.0";
|
|
3
|
+
export declare const SPEC_VERSION: "2.0";
|
|
4
|
+
export declare const SUPPORTED_SPEC_VERSIONS: readonly ["1.0", "2.0"];
|
|
5
|
+
export type SpecVersion = (typeof SUPPORTED_SPEC_VERSIONS)[number];
|
|
2
6
|
export declare const MEDIA_TYPE: "application/vnd.farcaster.snap+json";
|
|
3
7
|
export declare const EFFECT_VALUES: readonly ["confetti"];
|
|
8
|
+
export declare const POST_GRID_TAP_KEY: "grid_tap";
|
|
9
|
+
export declare const GRID_MIN_COLS = 2;
|
|
10
|
+
export declare const GRID_MAX_COLS = 32;
|
|
11
|
+
export declare const GRID_MIN_ROWS = 2;
|
|
12
|
+
export declare const GRID_MAX_ROWS = 16;
|
|
13
|
+
export declare const GRID_GAP_VALUES: readonly ["none", "sm", "md", "lg"];
|
|
14
|
+
export declare const MAX_ELEMENTS = 64;
|
|
15
|
+
export declare const MAX_ROOT_CHILDREN = 7;
|
|
16
|
+
export declare const MAX_CHILDREN = 6;
|
|
17
|
+
export declare const MAX_DEPTH = 4;
|
|
18
|
+
export declare const BAR_CHART_MAX_BARS = 6;
|
|
19
|
+
export declare const BAR_CHART_LABEL_MAX_CHARS = 40;
|
package/dist/constants.js
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
-
export const
|
|
1
|
+
export const SPEC_VERSION_1 = "1.0";
|
|
2
|
+
export const SPEC_VERSION_2 = "2.0";
|
|
3
|
+
export const SPEC_VERSION = SPEC_VERSION_2;
|
|
4
|
+
export const SUPPORTED_SPEC_VERSIONS = [SPEC_VERSION_1, SPEC_VERSION_2];
|
|
2
5
|
export const MEDIA_TYPE = "application/vnd.farcaster.snap+json";
|
|
3
6
|
export const EFFECT_VALUES = ["confetti"];
|
|
7
|
+
// ─── Pixel grid ────────────────────────────────────────
|
|
8
|
+
export const POST_GRID_TAP_KEY = "grid_tap";
|
|
9
|
+
export const GRID_MIN_COLS = 2;
|
|
10
|
+
export const GRID_MAX_COLS = 32;
|
|
11
|
+
export const GRID_MIN_ROWS = 2;
|
|
12
|
+
export const GRID_MAX_ROWS = 16;
|
|
13
|
+
export const GRID_GAP_VALUES = ["none", "sm", "md", "lg"];
|
|
14
|
+
// ─── Snap structural limits ───────────────────────────
|
|
15
|
+
export const MAX_ELEMENTS = 64;
|
|
16
|
+
export const MAX_ROOT_CHILDREN = 7;
|
|
17
|
+
export const MAX_CHILDREN = 6;
|
|
18
|
+
export const MAX_DEPTH = 4;
|
|
19
|
+
// ─── Bar chart ─────────────────────────────────────────
|
|
20
|
+
export const BAR_CHART_MAX_BARS = 6;
|
|
21
|
+
export const BAR_CHART_LABEL_MAX_CHARS = 40;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
export type { Spec as SnapSpec, UIElement as SnapUIElement } from "@json-render/core";
|
|
2
|
-
export { SPEC_VERSION, MEDIA_TYPE, EFFECT_VALUES, } from "./constants.js";
|
|
1
|
+
export type { Spec as SnapSpec, UIElement as SnapUIElement, } from "@json-render/core";
|
|
2
|
+
export { SPEC_VERSION, SPEC_VERSION_1, SPEC_VERSION_2, SUPPORTED_SPEC_VERSIONS, type SpecVersion, MEDIA_TYPE, EFFECT_VALUES, POST_GRID_TAP_KEY, MAX_ELEMENTS, MAX_ROOT_CHILDREN, MAX_CHILDREN, MAX_DEPTH, } from "./constants.js";
|
|
3
3
|
export { DEFAULT_THEME_ACCENT, PALETTE_COLOR, PALETTE_COLOR_ACCENT, PALETTE_COLOR_VALUES, PALETTE_LIGHT_HEX, PALETTE_DARK_HEX, type PaletteColor, } from "./colors.js";
|
|
4
|
-
export { ACTION_TYPE_GET, ACTION_TYPE_POST, snapResponseSchema, payloadSchema, type SnapAction, type SnapContext, type SnapResponse, type SnapHandlerResult, type SnapFunction, type SnapPayload, } from "./schemas.js";
|
|
5
|
-
export { validateSnapResponse, type ValidationResult
|
|
6
|
-
export { type DataStoreValue, type SnapDataStore, type SnapDataStoreOperations, createDefaultDataStore, createInMemoryDataStore, } from "./dataStore.js";
|
|
7
|
-
export { type Middleware, useMiddleware } from "./middleware.js";
|
|
4
|
+
export { ACTION_TYPE_GET, ACTION_TYPE_POST, snapResponseSchema, payloadSchema, type SnapAction, type SnapContext, type SnapResponse, type SnapHandlerResult, type SnapElementInput, type SnapSpecInput, type SnapFunction, type SnapPayload, } from "./schemas.js";
|
|
5
|
+
export { validateSnapResponse, type ValidationResult } from "./validator.js";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
export { SPEC_VERSION, MEDIA_TYPE, EFFECT_VALUES, } from "./constants.js";
|
|
1
|
+
export { SPEC_VERSION, SPEC_VERSION_1, SPEC_VERSION_2, SUPPORTED_SPEC_VERSIONS, MEDIA_TYPE, EFFECT_VALUES, POST_GRID_TAP_KEY, MAX_ELEMENTS, MAX_ROOT_CHILDREN, MAX_CHILDREN, MAX_DEPTH, } from "./constants.js";
|
|
2
2
|
export { DEFAULT_THEME_ACCENT, PALETTE_COLOR, PALETTE_COLOR_ACCENT, PALETTE_COLOR_VALUES, PALETTE_LIGHT_HEX, PALETTE_DARK_HEX, } from "./colors.js";
|
|
3
3
|
export { ACTION_TYPE_GET, ACTION_TYPE_POST, snapResponseSchema, payloadSchema, } from "./schemas.js";
|
|
4
|
-
export { validateSnapResponse
|
|
5
|
-
export { createDefaultDataStore, createInMemoryDataStore, } from "./dataStore.js";
|
|
6
|
-
export { useMiddleware } from "./middleware.js";
|
|
4
|
+
export { validateSnapResponse } from "./validator.js";
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
export declare function SnapPreviewAccentProvider({ pageAccent, children, }: {
|
|
2
|
+
export declare function SnapPreviewAccentProvider({ pageAccent, appearance, children, }: {
|
|
3
3
|
pageAccent: string | undefined;
|
|
4
|
+
appearance?: "light" | "dark";
|
|
4
5
|
children: ReactNode;
|
|
5
6
|
}): import("react/jsx-runtime").JSX.Element;
|
|
6
7
|
export declare function useSnapPreviewPageAccent(): string | undefined;
|
|
8
|
+
export declare function useSnapAppearance(): "light" | "dark";
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { createContext, useContext } from "react";
|
|
4
|
-
const
|
|
5
|
-
export function SnapPreviewAccentProvider({ pageAccent, children, }) {
|
|
6
|
-
return (_jsx(
|
|
4
|
+
const SnapPreviewContext = createContext(null);
|
|
5
|
+
export function SnapPreviewAccentProvider({ pageAccent, appearance = "dark", children, }) {
|
|
6
|
+
return (_jsx(SnapPreviewContext.Provider, { value: { pageAccent, appearance }, children: children }));
|
|
7
7
|
}
|
|
8
8
|
export function useSnapPreviewPageAccent() {
|
|
9
|
-
return useContext(
|
|
9
|
+
return useContext(SnapPreviewContext)?.pageAccent;
|
|
10
|
+
}
|
|
11
|
+
export function useSnapAppearance() {
|
|
12
|
+
return useContext(SnapPreviewContext)?.appearance ?? "dark";
|
|
10
13
|
}
|
|
@@ -15,6 +15,8 @@ import { SnapStack } from "./components/stack.js";
|
|
|
15
15
|
import { SnapSwitch } from "./components/switch.js";
|
|
16
16
|
import { SnapText } from "./components/text.js";
|
|
17
17
|
import { SnapToggleGroup } from "./components/toggle-group.js";
|
|
18
|
+
import { SnapBarChart } from "./components/bar-chart.js";
|
|
19
|
+
import { SnapCellGrid } from "./components/cell-grid.js";
|
|
18
20
|
/**
|
|
19
21
|
* Maps snap json-render catalog types to React components.
|
|
20
22
|
* Keys match the snap wire-format `type` strings exactly.
|
|
@@ -34,4 +36,6 @@ export const SnapCatalogView = createRenderer(snapJsonRenderCatalog, {
|
|
|
34
36
|
switch: SnapSwitch,
|
|
35
37
|
text: SnapText,
|
|
36
38
|
toggle_group: SnapToggleGroup,
|
|
39
|
+
bar_chart: SnapBarChart,
|
|
40
|
+
cell_grid: SnapCellGrid,
|
|
37
41
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export declare function SnapActionButton({ element
|
|
1
|
+
export declare function SnapActionButton({ element, emit, }: {
|
|
2
2
|
element: {
|
|
3
3
|
props: Record<string, unknown>;
|
|
4
|
+
on?: Record<string, unknown>;
|
|
4
5
|
};
|
|
5
6
|
emit: (name: string) => void;
|
|
6
7
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,22 +1,41 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { ExternalLink } from "lucide-react";
|
|
3
5
|
import { Button } from "@neynar/ui/button";
|
|
4
6
|
import { cn } from "@neynar/ui/utils";
|
|
5
|
-
import {
|
|
7
|
+
import { useSnapColors } from "../hooks/use-snap-colors.js";
|
|
6
8
|
import { ICON_MAP } from "./icon.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
function isExternalLinkAction(on) {
|
|
10
|
+
if (!on)
|
|
11
|
+
return false;
|
|
12
|
+
const press = on.press;
|
|
13
|
+
if (!press)
|
|
14
|
+
return false;
|
|
15
|
+
return press.action === "open_url";
|
|
16
|
+
}
|
|
17
|
+
export function SnapActionButton({ element, emit, }) {
|
|
18
|
+
const { props } = element;
|
|
14
19
|
const label = String(props.label ?? "Action");
|
|
15
|
-
const variant =
|
|
20
|
+
const variant = String(props.variant ?? "secondary");
|
|
21
|
+
const isPrimary = variant === "primary";
|
|
16
22
|
const iconName = props.icon ? String(props.icon) : undefined;
|
|
17
|
-
const
|
|
23
|
+
const colors = useSnapColors();
|
|
24
|
+
const [hovered, setHovered] = useState(false);
|
|
18
25
|
const Icon = iconName ? ICON_MAP[iconName] : undefined;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
const showExternalIcon = isExternalLinkAction(element.on);
|
|
27
|
+
const style = isPrimary
|
|
28
|
+
? {
|
|
29
|
+
backgroundColor: hovered ? colors.accentHover : colors.accent,
|
|
30
|
+
color: colors.accentFg,
|
|
31
|
+
borderColor: "transparent",
|
|
32
|
+
}
|
|
33
|
+
: {
|
|
34
|
+
backgroundColor: hovered
|
|
35
|
+
? `color-mix(in srgb, ${colors.accent} 15%, transparent)`
|
|
36
|
+
: colors.muted,
|
|
37
|
+
color: colors.text,
|
|
38
|
+
borderColor: "transparent",
|
|
39
|
+
};
|
|
40
|
+
return (_jsx("div", { className: "w-full min-w-0 flex-1", children: _jsxs(Button, { type: "button", variant: isPrimary ? "default" : "secondary", className: cn("w-full gap-2"), style: style, onClick: () => emit("press"), onPointerEnter: () => setHovered(true), onPointerLeave: () => setHovered(false), children: [Icon && _jsx(Icon, { size: 16 }), label, showExternalIcon && (_jsx(ExternalLink, { size: 14, style: { opacity: 0.6 } }))] }) }));
|
|
22
41
|
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Badge } from "@neynar/ui/badge";
|
|
4
|
-
import {
|
|
4
|
+
import { useSnapColors } from "../hooks/use-snap-colors.js";
|
|
5
5
|
import { ICON_MAP } from "./icon.js";
|
|
6
6
|
export function SnapBadge({ element: { props }, }) {
|
|
7
7
|
const content = String(props.label ?? "");
|
|
8
|
+
const variant = String(props.variant ?? "default");
|
|
8
9
|
const color = props.color ? String(props.color) : undefined;
|
|
9
10
|
const iconName = props.icon ? String(props.icon) : undefined;
|
|
10
|
-
const
|
|
11
|
-
const
|
|
11
|
+
const colors = useSnapColors();
|
|
12
|
+
const badgeColor = colors.colorHex(color);
|
|
12
13
|
const Icon = iconName ? ICON_MAP[iconName] : undefined;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
: undefined, children: [Icon && _jsx(Icon, { size: 12 }), content] }) }));
|
|
14
|
+
const style = variant === "outline"
|
|
15
|
+
? { borderColor: badgeColor, color: badgeColor, backgroundColor: "transparent" }
|
|
16
|
+
: { backgroundColor: `${badgeColor}20`, color: badgeColor, borderColor: "transparent" };
|
|
17
|
+
return (_jsxs(Badge, { variant: variant, className: "gap-1", style: style, children: [Icon && _jsx(Icon, { size: 12 }), content] }));
|
|
18
18
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useSnapColors } from "../hooks/use-snap-colors.js";
|
|
4
|
+
export function SnapBarChart({ element: { props }, }) {
|
|
5
|
+
const colors = useSnapColors();
|
|
6
|
+
const bars = Array.isArray(props.bars) ? props.bars : [];
|
|
7
|
+
const chartColor = props.color ? String(props.color) : undefined;
|
|
8
|
+
const maxVal = props.max != null
|
|
9
|
+
? Number(props.max)
|
|
10
|
+
: Math.max(...bars.map((b) => Number(b.value ?? 0)), 1);
|
|
11
|
+
function barFill(bar) {
|
|
12
|
+
if (bar.color)
|
|
13
|
+
return colors.colorHex(bar.color);
|
|
14
|
+
return colors.colorHex(chartColor);
|
|
15
|
+
}
|
|
16
|
+
return (_jsx("div", { className: "flex w-full flex-col gap-2", children: bars.map((bar, i) => {
|
|
17
|
+
const value = Number(bar.value ?? 0);
|
|
18
|
+
const pct = maxVal > 0 ? Math.min(100, (value / maxVal) * 100) : 0;
|
|
19
|
+
const fill = barFill(bar);
|
|
20
|
+
return (_jsxs("div", { className: "flex w-full items-center gap-2", children: [_jsx("span", { className: "w-20 shrink-0 truncate text-right text-xs", style: { color: colors.textMuted }, children: String(bar.label ?? "") }), _jsx("div", { className: "h-2.5 flex-1 overflow-hidden rounded-full", style: { backgroundColor: colors.muted }, children: _jsx("div", { className: "h-full rounded-full transition-all", style: {
|
|
21
|
+
width: `${pct}%`,
|
|
22
|
+
minWidth: pct > 0 ? 4 : 0,
|
|
23
|
+
backgroundColor: fill,
|
|
24
|
+
} }) }), _jsx("span", { className: "w-8 shrink-0 text-xs tabular-nums", style: { color: colors.textMuted }, children: value })] }, i));
|
|
25
|
+
}) }));
|
|
26
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useStateStore } from "@json-render/react";
|
|
4
|
+
import { cn } from "@neynar/ui/utils";
|
|
5
|
+
import { POST_GRID_TAP_KEY } from "@farcaster/snap";
|
|
6
|
+
import { useSnapColors } from "../hooks/use-snap-colors.js";
|
|
7
|
+
export function SnapCellGrid({ element: { props }, }) {
|
|
8
|
+
const { get, set } = useStateStore();
|
|
9
|
+
const colors = useSnapColors();
|
|
10
|
+
const cols = Number(props.cols ?? 2);
|
|
11
|
+
const rows = Number(props.rows ?? 2);
|
|
12
|
+
const select = String(props.select ?? "off");
|
|
13
|
+
const interactive = select !== "off";
|
|
14
|
+
const isMultiple = select === "multiple";
|
|
15
|
+
const cells = Array.isArray(props.cells) ? props.cells : [];
|
|
16
|
+
const gap = String(props.gap ?? "sm");
|
|
17
|
+
const gapMap = { none: 0, sm: 1, md: 2, lg: 4 };
|
|
18
|
+
const gapPx = gapMap[gap] ?? 1;
|
|
19
|
+
const rowHeight = typeof props.rowHeight === "number" ? props.rowHeight : 28;
|
|
20
|
+
const name = props.name ? String(props.name) : POST_GRID_TAP_KEY;
|
|
21
|
+
const tapPath = `/inputs/${name}`;
|
|
22
|
+
const tapRaw = get(tapPath);
|
|
23
|
+
// Parse selection — single mode: "row,col" string; multi mode: "row,col|row,col|..." string
|
|
24
|
+
const selectedSet = new Set();
|
|
25
|
+
if (typeof tapRaw === "string" && tapRaw.length > 0) {
|
|
26
|
+
for (const part of tapRaw.split("|")) {
|
|
27
|
+
if (part.includes(","))
|
|
28
|
+
selectedSet.add(part);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const isSelected = (r, c) => selectedSet.has(`${r},${c}`);
|
|
32
|
+
const handleTap = (r, c) => {
|
|
33
|
+
const key = `${r},${c}`;
|
|
34
|
+
if (isMultiple) {
|
|
35
|
+
const next = new Set(selectedSet);
|
|
36
|
+
if (next.has(key))
|
|
37
|
+
next.delete(key);
|
|
38
|
+
else
|
|
39
|
+
next.add(key);
|
|
40
|
+
set(tapPath, [...next].join("|"));
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
set(tapPath, key);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const cellMap = new Map();
|
|
47
|
+
for (const c of cells) {
|
|
48
|
+
cellMap.set(`${Number(c.row)},${Number(c.col)}`, {
|
|
49
|
+
color: c.color,
|
|
50
|
+
content: c.content != null ? String(c.content) : undefined,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
const cellEls = [];
|
|
54
|
+
for (let r = 0; r < rows; r++) {
|
|
55
|
+
for (let c = 0; c < cols; c++) {
|
|
56
|
+
const cell = cellMap.get(`${r},${c}`);
|
|
57
|
+
const selected = interactive && isSelected(r, c);
|
|
58
|
+
const bg = cell?.color ? colors.colorHex(cell.color) : "transparent";
|
|
59
|
+
cellEls.push(_jsx("div", { role: interactive ? "button" : undefined, tabIndex: interactive ? 0 : undefined, onClick: interactive ? () => handleTap(r, c) : undefined, onKeyDown: interactive
|
|
60
|
+
? (e) => {
|
|
61
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
handleTap(r, c);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
: undefined, className: cn("flex items-center justify-center rounded text-xs font-semibold", interactive ? "cursor-pointer select-none" : "cursor-default"), style: {
|
|
67
|
+
height: rowHeight,
|
|
68
|
+
background: bg,
|
|
69
|
+
boxShadow: selected
|
|
70
|
+
? `inset 0 0 0 1px ${colors.mode === "dark" ? "#000" : "#fff"}, inset 0 0 0 2px ${colors.mode === "dark" ? "#fff" : "#000"}`
|
|
71
|
+
: undefined,
|
|
72
|
+
}, children: cell?.content ?? "" }, `${r}-${c}`));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const selectionLabel = interactive && selectedSet.size > 0
|
|
76
|
+
? `inputs.${name}: ${[...selectedSet].join(isMultiple ? " | " : "")}`
|
|
77
|
+
: null;
|
|
78
|
+
return (_jsxs("div", { children: [_jsx("div", { style: {
|
|
79
|
+
display: "grid",
|
|
80
|
+
width: "100%",
|
|
81
|
+
gridTemplateColumns: `repeat(${cols}, 1fr)`,
|
|
82
|
+
gap: gapPx,
|
|
83
|
+
padding: 4,
|
|
84
|
+
borderRadius: 8,
|
|
85
|
+
backgroundColor: colors.muted,
|
|
86
|
+
}, children: cellEls }), selectionLabel && (_jsx("div", { className: "mt-1.5 truncate text-xs font-mono", style: { color: colors.textMuted }, children: selectionLabel }))] }));
|
|
87
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { ArrowRight, ArrowLeft, ExternalLink, ChevronRight, Check, X, AlertTriangle, Info, Clock, Heart, MessageCircle, Repeat, Share, User, Users, Star, Trophy, Zap, Flame, Gift, ImageIcon, Play, Pause, Wallet, Coins, Plus, Minus, RefreshCw, Bookmark, ThumbsUp, ThumbsDown, TrendingUp, TrendingDown, } from "lucide-react";
|
|
4
|
-
import {
|
|
4
|
+
import { useSnapColors } from "../hooks/use-snap-colors.js";
|
|
5
5
|
export const ICON_MAP = {
|
|
6
6
|
"arrow-right": ArrowRight,
|
|
7
7
|
"arrow-left": ArrowLeft,
|
|
@@ -45,16 +45,10 @@ export function SnapIcon({ element: { props }, }) {
|
|
|
45
45
|
const name = String(props.name ?? "info");
|
|
46
46
|
const size = SIZE_PX[String(props.size ?? "md")] ?? 20;
|
|
47
47
|
const color = props.color ? String(props.color) : undefined;
|
|
48
|
-
const
|
|
48
|
+
const colors = useSnapColors();
|
|
49
49
|
const Icon = ICON_MAP[name];
|
|
50
50
|
if (!Icon)
|
|
51
51
|
return null;
|
|
52
|
-
const
|
|
53
|
-
return (_jsx("span", { style: {
|
|
54
|
-
display: "inline-flex",
|
|
55
|
-
alignItems: "center",
|
|
56
|
-
...(isAccent ? accentStyle : {}),
|
|
57
|
-
}, children: _jsx(Icon, { size: size, style: isAccent
|
|
58
|
-
? { color: "var(--snap-accent, currentColor)" }
|
|
59
|
-
: { color: `var(--snap-color-${color}, currentColor)` } }) }));
|
|
52
|
+
const iconColor = colors.colorHex(color);
|
|
53
|
+
return (_jsx("span", { style: { display: "inline-flex", alignItems: "center" }, children: _jsx(Icon, { size: size, style: { color: iconColor } }) }));
|
|
60
54
|
}
|
|
@@ -4,15 +4,21 @@ import { useId } from "react";
|
|
|
4
4
|
import { useStateStore } from "@json-render/react";
|
|
5
5
|
import { Input } from "@neynar/ui/input";
|
|
6
6
|
import { Label } from "@neynar/ui/label";
|
|
7
|
+
import { useSnapColors } from "../hooks/use-snap-colors.js";
|
|
7
8
|
export function SnapInput({ element: { props }, }) {
|
|
8
|
-
const id = useId();
|
|
9
9
|
const { get, set } = useStateStore();
|
|
10
|
+
const colors = useSnapColors();
|
|
10
11
|
const name = String(props.name ?? "input");
|
|
11
|
-
const
|
|
12
|
+
const type = String(props.type ?? "text");
|
|
12
13
|
const label = props.label ? String(props.label) : undefined;
|
|
13
14
|
const placeholder = props.placeholder ? String(props.placeholder) : undefined;
|
|
14
|
-
const maxLength =
|
|
15
|
-
const
|
|
16
|
-
const value =
|
|
17
|
-
|
|
15
|
+
const maxLength = props.maxLength ? Number(props.maxLength) : undefined;
|
|
16
|
+
const path = `/inputs/${name}`;
|
|
17
|
+
const value = get(path) ?? (props.defaultValue != null ? String(props.defaultValue) : "");
|
|
18
|
+
const id = useId();
|
|
19
|
+
return (_jsxs("div", { className: "w-full space-y-1.5", children: [label && (_jsx(Label, { htmlFor: id, style: { color: colors.text }, children: label })), _jsx(Input, { id: id, type: type === "number" ? "number" : "text", placeholder: placeholder, maxLength: maxLength, value: value, onChange: (e) => set(path, e.target.value), style: {
|
|
20
|
+
backgroundColor: colors.inputBg,
|
|
21
|
+
borderColor: colors.inputBorder,
|
|
22
|
+
color: colors.text,
|
|
23
|
+
} })] }));
|
|
18
24
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Children, Fragment } from "react";
|
|
4
4
|
import { cn } from "@neynar/ui/utils";
|
|
5
|
+
import { useSnapColors } from "../hooks/use-snap-colors.js";
|
|
5
6
|
const GAP_MAP = {
|
|
6
7
|
none: "gap-0",
|
|
7
8
|
sm: "gap-1",
|
|
@@ -13,5 +14,6 @@ export function SnapItemGroup({ element: { props }, children, }) {
|
|
|
13
14
|
const separator = Boolean(props.separator);
|
|
14
15
|
const gap = GAP_MAP[String(props.gap ?? "sm")] ?? "gap-1";
|
|
15
16
|
const items = Children.toArray(children);
|
|
16
|
-
|
|
17
|
+
const colors = useSnapColors();
|
|
18
|
+
return (_jsx("div", { className: cn("flex flex-col", border && "rounded-lg border", gap), style: border ? { borderColor: colors.border } : undefined, children: items.map((child, i) => (_jsxs(Fragment, { children: [separator && i > 0 && (_jsx("div", { className: "h-px", style: { backgroundColor: colors.border } })), child] }, i))) }));
|
|
17
19
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function SnapItem({ element: { props }, children, }: {
|
|
1
|
+
export declare function SnapItem({ element: { props, children: childIds }, children, }: {
|
|
3
2
|
element: {
|
|
4
3
|
props: Record<string, unknown>;
|
|
4
|
+
children?: string[];
|
|
5
5
|
};
|
|
6
|
-
children?: ReactNode;
|
|
6
|
+
children?: React.ReactNode;
|
|
7
7
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Item, ItemContent, ItemTitle, ItemDescription, ItemActions, } from "@neynar/ui/item";
|
|
4
|
-
|
|
4
|
+
import { useSnapColors } from "../hooks/use-snap-colors.js";
|
|
5
|
+
export function SnapItem({ element: { props, children: childIds }, children, }) {
|
|
5
6
|
const title = String(props.title ?? "");
|
|
6
7
|
const description = props.description ? String(props.description) : undefined;
|
|
7
|
-
const
|
|
8
|
-
return (_jsxs(Item, {
|
|
8
|
+
const colors = useSnapColors();
|
|
9
|
+
return (_jsxs(Item, { className: "flex-1 py-1.5 px-2.5", children: [_jsxs(ItemContent, { className: "gap-0.5", children: [_jsx(ItemTitle, { style: { color: colors.text }, children: title }), description && (_jsx(ItemDescription, { className: "mt-0", style: { color: colors.textMuted }, children: description }))] }), childIds && childIds.length > 0 && _jsx(ItemActions, { children: children })] }));
|
|
9
10
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
3
|
+
import { useSnapColors } from "../hooks/use-snap-colors.js";
|
|
4
4
|
export function SnapProgress({ element: { props }, }) {
|
|
5
|
-
const
|
|
5
|
+
const colors = useSnapColors();
|
|
6
6
|
const value = Number(props.value ?? 0);
|
|
7
7
|
const max = Math.max(1, Number(props.max ?? 100));
|
|
8
8
|
const percent = Math.min(100, Math.max(0, (value / max) * 100));
|
|
9
9
|
const label = props.label ? String(props.label) : null;
|
|
10
|
-
return (_jsxs("div", { className: "flex w-full flex-1 flex-col gap-1",
|
|
10
|
+
return (_jsxs("div", { className: "flex w-full flex-1 flex-col gap-1", children: [label && (_jsx("span", { className: "text-xs", style: { color: colors.textMuted }, children: label })), _jsx("div", { className: "h-2.5 w-full overflow-hidden rounded-full", style: { backgroundColor: colors.muted }, children: _jsx("div", { className: "h-full rounded-full transition-all", style: { width: `${percent}%`, backgroundColor: colors.accent } }) })] }));
|
|
11
11
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { Separator } from "@neynar/ui/separator";
|
|
4
|
+
import { useSnapColors } from "../hooks/use-snap-colors.js";
|
|
4
5
|
export function SnapSeparator({ element: { props }, }) {
|
|
5
6
|
const orientation = props.orientation ?? "horizontal";
|
|
6
|
-
|
|
7
|
+
const colors = useSnapColors();
|
|
8
|
+
return (_jsx(Separator, { orientation: orientation, style: { backgroundColor: colors.border } }));
|
|
7
9
|
}
|
|
@@ -2,20 +2,25 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useStateStore } from "@json-render/react";
|
|
4
4
|
import { Label } from "@neynar/ui/label";
|
|
5
|
-
import {
|
|
6
|
-
// TODO: switch back to @neynar/ui/slider once Base UI fixes the inline
|
|
7
|
-
// <script> tag that triggers a React console warning on client render.
|
|
5
|
+
import { useSnapColors } from "../hooks/use-snap-colors.js";
|
|
8
6
|
export function SnapSlider({ element: { props }, }) {
|
|
9
7
|
const { get, set } = useStateStore();
|
|
10
|
-
const
|
|
8
|
+
const colors = useSnapColors();
|
|
11
9
|
const name = String(props.name ?? "slider");
|
|
12
|
-
const path = `/inputs/${name}`;
|
|
13
|
-
const label = props.label ? String(props.label) : undefined;
|
|
14
10
|
const min = Number(props.min ?? 0);
|
|
15
11
|
const max = Number(props.max ?? 100);
|
|
16
|
-
const step =
|
|
17
|
-
const
|
|
12
|
+
const step = Number(props.step ?? 1);
|
|
13
|
+
const label = props.label ? String(props.label) : undefined;
|
|
14
|
+
const showValue = props.showValue === true;
|
|
15
|
+
const path = `/inputs/${name}`;
|
|
18
16
|
const raw = get(path);
|
|
19
|
-
const value = raw
|
|
20
|
-
|
|
17
|
+
const value = raw !== undefined
|
|
18
|
+
? Number(raw)
|
|
19
|
+
: props.defaultValue !== undefined
|
|
20
|
+
? Number(props.defaultValue)
|
|
21
|
+
: (min + max) / 2;
|
|
22
|
+
return (_jsxs("div", { className: "flex w-full flex-col gap-1.5", children: [label && (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Label, { style: { color: colors.text }, children: label }), showValue && (_jsx("span", { style: { color: colors.textMuted, fontSize: 13, lineHeight: "18px" }, children: Math.round(value) }))] })), _jsx("input", { type: "range", min: min, max: max, step: step, value: value, onChange: (e) => set(path, Number(e.target.value)), className: "w-full h-2.5 rounded-full appearance-none cursor-pointer", style: {
|
|
23
|
+
backgroundColor: colors.muted,
|
|
24
|
+
accentColor: colors.accent,
|
|
25
|
+
} })] }));
|
|
21
26
|
}
|
|
@@ -2,22 +2,20 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useId } from "react";
|
|
4
4
|
import { useStateStore } from "@json-render/react";
|
|
5
|
-
import { Label } from "@neynar/ui/label";
|
|
6
5
|
import { Switch } from "@neynar/ui/switch";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { useSnapAccentScopeStyle } from "../hooks/use-snap-accent.js";
|
|
6
|
+
import { Label } from "@neynar/ui/label";
|
|
7
|
+
import { useSnapColors } from "../hooks/use-snap-colors.js";
|
|
10
8
|
export function SnapSwitch({ element: { props }, }) {
|
|
11
|
-
const id = useId();
|
|
12
9
|
const { get, set } = useStateStore();
|
|
13
|
-
const
|
|
14
|
-
const accentStyle = useSnapAccentScopeStyle();
|
|
10
|
+
const colors = useSnapColors();
|
|
15
11
|
const name = String(props.name ?? "switch");
|
|
16
|
-
const path = `/inputs/${name}`;
|
|
17
12
|
const label = props.label ? String(props.label) : undefined;
|
|
18
|
-
const
|
|
13
|
+
const path = `/inputs/${name}`;
|
|
19
14
|
const raw = get(path);
|
|
20
|
-
const checked = raw
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
const checked = raw !== undefined ? Boolean(raw) : Boolean(props.defaultChecked);
|
|
16
|
+
const id = useId();
|
|
17
|
+
return (_jsxs("div", { className: "flex items-center justify-between gap-3", children: [label && (_jsx(Label, { htmlFor: id, className: "font-normal", style: { color: colors.text }, children: label })), _jsx(Switch, { id: id, checked: checked, onCheckedChange: (v) => set(path, v), style: {
|
|
18
|
+
backgroundColor: checked ? colors.accent : colors.muted,
|
|
19
|
+
borderColor: checked ? colors.accent : colors.inputBorder,
|
|
20
|
+
} })] }));
|
|
23
21
|
}
|