- );
- })}
-
-
- );
-};
-
-interface PageProps {
- tableOfContents?: Array<{
- text: string;
- id: string;
- level: string;
- }>;
-}
-
-export const Page = (props: React.PropsWithChildren) => {
- const { bannerExpanded } = React.useContext(AppContext);
-
- const bannerHeight = '72px';
- const maxH = `calc(100vh - 88px - ${bannerExpanded ? bannerHeight : '0px'})`;
- const minH = `calc(100vh - 88px - 105px - ${
- bannerExpanded ? bannerHeight : '0px'
- })`;
-
- return (
-
- Skip to Main Content
-
-
-
-
-
-
-
-
-
-
-
-
-
- {props.children}
-
-
-
-
-
- {props.tableOfContents && (
-
- )}
-
-
-
-
-
- );
-};
diff --git a/docs/site/components/PlayerTeam.tsx b/docs/site/components/PlayerTeam.tsx
deleted file mode 100644
index 9d06e4d4b..000000000
--- a/docs/site/components/PlayerTeam.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import React from 'react';
-import { Avatar, SimpleGrid, VStack, Text } from '@chakra-ui/react';
-import teamdata from '../config/team.json';
-
-/**
- * Individual Profile card with avatar, name and domain vertically stacked
- */
-const ProfileCard = (props: any) => {
- return (
-
-
- {props.profile.name}
- {props.profile.domain.join(', ')}
-
- );
-};
-
-/**
- * Component to render Player Team cards
- */
-export const PlayerTeam = () => {
- return (
-
- {teamdata
- .sort(() => 0.5 - Math.random())
- .map((element) => {
- return ;
- })}
-
- );
-};
diff --git a/docs/site/components/Search.tsx b/docs/site/components/Search.tsx
deleted file mode 100644
index 80d82c930..000000000
--- a/docs/site/components/Search.tsx
+++ /dev/null
@@ -1,177 +0,0 @@
-import React from "react";
-import {
- Input,
- Box,
- Popover,
- PopoverContent,
- PopoverAnchor,
- Button,
- chakra,
- Heading,
- Text,
- InputGroup,
- useOutsideClick,
- UnorderedList,
- InputLeftElement,
- HStack,
-} from "@chakra-ui/react";
-import { SearchIcon, ChevronRightIcon } from "@chakra-ui/icons";
-import { Link } from "react-router-dom";
-import lunr from "lunr";
-import { AlgoliaSearch } from "./AlgoliaSearch";
-
-interface SearchIndex {
- /** The title of the page */
- title: string;
-
- /** The closest heading */
- header: string;
-
- /** the route to the page */
- path: string;
-
- /** The raw content */
- // eslint-disable-next-line react/no-unused-prop-types
- content: string;
-}
-
-const createSearchIndex = async () => {
- const searchIndex = (await import(
- "../config/search-index.json"
- )) as unknown as {
- default: Record;
- };
-
- const idx = lunr((builder) => {
- builder.ref("path");
- builder.field("title");
- builder.field("header");
- builder.field("content");
-
- Object.values(searchIndex.default).forEach((page) => {
- builder.add(page);
- });
- });
-
- return {
- searchIndex: searchIndex.default,
- idx,
- };
-};
-
-const useSearch = () => {
- const index = React.useMemo(() => createSearchIndex(), []);
- const [results, setResults] = React.useState([]);
-
- return {
- search: async (query: string) => {
- if (query === "") {
- setResults([]);
- } else {
- const searchIndex = await index;
- const searchResults = searchIndex.idx
- .search(query)
- .slice(0, 10)
- .map((r) => {
- return searchIndex.searchIndex[r.ref];
- })
- .filter((e) => e !== undefined);
-
- setResults(searchResults);
- }
- },
- clear: () => {
- setResults([]);
- },
- results,
- };
-};
-
-const SearchResult = (props: SearchIndex) => {
- return (
-
-
-
-
-
- );
-};
-
-export const FallbackSearchInput = (): React.JSX.Element => {
- const { search, results, clear } = useSearch();
- const [searchActive, setSearchActive] = React.useState(false);
- const [query, setQuery] = React.useState("");
- const inputRef = React.useRef(null);
- const searchRef = React.useRef(null);
-
- const reset = React.useCallback(() => {
- clear();
- setQuery("");
- setSearchActive(false);
- }, [clear, setQuery, setSearchActive]);
-
- useOutsideClick({
- ref: searchRef,
- handler: reset,
- });
-
- return (
-
-
-
-
-
-
-
- {
- if (searchActive) {
- search(e.target.value);
- }
-
- setQuery(e.target.value);
- }}
- onFocus={() => {
- setSearchActive(true);
- }}
- />
-
-
- {searchActive && results.length > 0 && (
-
-
-
- {results.map((r) => (
-
- ))}
-
-
-
- )}
-
-
- );
-};
-
-export const SearchInput = (): React.JSX.Element => {
- // Only use algolia search if we're on the /latest/ version
- // it's the only one that's indexed
- if (
- typeof window !== "undefined" &&
- window.location.pathname.includes("/latest/")
- ) {
- return ;
- }
-
- return ;
-};
diff --git a/docs/site/components/SiteBanner.tsx b/docs/site/components/SiteBanner.tsx
deleted file mode 100644
index 33111336e..000000000
--- a/docs/site/components/SiteBanner.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import React from 'react';
-import { Alert, AlertIcon, Box, CloseButton } from '@chakra-ui/react';
-import { AppContext } from './Context';
-
-export const WarningBanner = (props: React.PropsWithChildren) => {
- const { bannerExpanded, setBannerExpanded } = React.useContext(AppContext);
-
- if (!bannerExpanded) {
- return null;
- }
-
- return (
-
-
- {props.children}
- {
- setBannerExpanded(false);
- }}
- />
-
- );
-};
diff --git a/docs/site/components/chakra-theme.ts b/docs/site/components/chakra-theme.ts
deleted file mode 100644
index 553f077d9..000000000
--- a/docs/site/components/chakra-theme.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { extendTheme } from '@chakra-ui/react';
-
-export const colors = {
- transparent: 'transparent',
- black: '#000',
- white: '#fff',
- gray: {
- 50: '#dee1e3',
- 100: '#cfd3d7',
- 200: '#bfc5c9',
- 300: '#adb4b9',
- 400: '#98a1a8',
- 500: '#7f8b92',
- 600: '#374147',
- 700: '#374147',
- 800: '#121212',
- },
- red: {},
- orange: {},
- yellow: {},
- green: {},
- teal: {},
- blue: {
- 50: '#f6fafd',
- 100: '#e2eff9',
- 200: '#cce4f5',
- 300: '#b5d8f0',
- 400: '#9bcaeb',
- 500: '#7dbae5',
- 600: '#5aa7de',
- 700: '#2d8fd5',
- 800: '#0070b6',
- 900: '#055393',
- },
- cyan: {},
- purple: {},
- pink: {},
-};
-
-export const theme = extendTheme({
- colors,
-});
diff --git a/docs/site/components/code-highlight/index.tsx b/docs/site/components/code-highlight/index.tsx
deleted file mode 100644
index d8eccd93d..000000000
--- a/docs/site/components/code-highlight/index.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import React from "react";
-import { Box, useColorModeValue } from "@chakra-ui/react";
-import {
- Prism as SyntaxHighlighter,
- SyntaxHighlighterProps,
-} from "react-syntax-highlighter";
-
-import { light, dark } from "./prism-colors";
-
-export const useCodeStyle = () => {
- const style = useColorModeValue(light, dark);
-
- return style;
-};
-
-export const CodeHighlight = (props: SyntaxHighlighterProps) => {
- const borderColor = useColorModeValue("gray.100", "gray.800");
-
- return (
-
-
-
- );
-};
diff --git a/docs/site/components/code-highlight/prism-colors.ts b/docs/site/components/code-highlight/prism-colors.ts
deleted file mode 100644
index 893f00cb0..000000000
--- a/docs/site/components/code-highlight/prism-colors.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import {
- coy,
- vscDarkPlus,
-} from 'react-syntax-highlighter/dist/cjs/styles/prism';
-
-export const light = {
- ...coy,
- pre: {
- margin: '.5em 0',
- },
- 'pre[class*="language-"]': {
- fontSize: '13px',
- textShadow: 'none',
- fontFamily:
- 'Menlo, Monaco, Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace',
- direction: 'ltr',
- textAlign: 'left',
- whiteSpace: 'pre',
- wordSpacing: 'normal',
- wordBreak: 'normal',
- lineHeight: '1.5',
- MozTabSize: '4',
- OTabSize: '4',
- tabSize: '4',
- WebkitHyphens: 'none',
- MozHyphens: 'none',
- msHyphens: 'none',
- hyphens: 'none',
- padding: '1em',
- margin: '.5em 0',
- overflow: 'auto',
- },
- 'code[class*="language-"]': {
- fontSize: '13px',
- textShadow: 'none',
- fontFamily:
- 'Menlo, Monaco, Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace',
- direction: 'ltr',
- textAlign: 'left',
- whiteSpace: 'pre',
- wordSpacing: 'normal',
- wordBreak: 'normal',
- lineHeight: '1.5',
- MozTabSize: '4',
- OTabSize: '4',
- tabSize: '4',
- WebkitHyphens: 'none',
- MozHyphens: 'none',
- msHyphens: 'none',
- hyphens: 'none',
- },
-};
-
-export const dark = {
- ...vscDarkPlus,
-};
diff --git a/docs/site/components/gh-icon.tsx b/docs/site/components/gh-icon.tsx
deleted file mode 100644
index a399b62af..000000000
--- a/docs/site/components/gh-icon.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import React from 'react';
-
-// https://github.com/chakra-ui/chakra-ui-docs/blob/main/src/components/header.tsx
-export const GithubIcon = React.forwardRef(
- (props: React.ComponentProps<'svg'>, ref) => (
-
- )
-);
diff --git a/docs/site/components/mdx-components.tsx b/docs/site/components/mdx-components.tsx
deleted file mode 100644
index ef1bf3207..000000000
--- a/docs/site/components/mdx-components.tsx
+++ /dev/null
@@ -1,302 +0,0 @@
-import React from "react";
-import {
- Alert as ChakraAlert,
- AlertStatus,
- Heading,
- Text,
- UnorderedList,
- OrderedList,
- ListItem,
- Code as ChakraCode,
- useColorMode,
- useColorModeValue,
- Tabs as ChakraTabs,
- TabList,
- TabPanels,
- Tab,
- TabPanel,
- Progress,
- Image,
- HStack,
- Table,
- Th,
- Tr,
- Td,
- Link as CLink,
- AlertIcon,
- Box,
- AlertTitle,
- AlertDescription,
-} from "@chakra-ui/react";
-import { MDXProviderComponents } from "@mdx-js/react";
-import { useNavigate } from "react-router";
-import { Link, useSearchParams } from "react-router-dom";
-import { CodeHighlight } from "./code-highlight";
-import { withBasePrefix } from "./Image";
-import { PlayerTeam } from "./PlayerTeam";
-
-/**
- * Generic Tab Component that extends Chakra's Tab
- */
-const GenericTab = (props: any) => {
- const name = props.nameMap?.get(props.mdxType.toLowerCase()) ?? props.mdxType;
- return {name};
-};
-
-/**
- * Tab Component specifically for Gradle to handle its multiple languages
- */
-const GradleTab = (props: any) => {
- const scriptLang = props.language;
- return {`Gradle ${scriptLang}`};
-};
-
-const CodeTabsNameMap = new Map([
- ["core", "Core"],
- ["react", "React"],
- ["ios", "iOS"],
- ["android", "Android"],
-]);
-
-const ContentTabsNameMap = new Map([
- ['json', 'JSON'],
- ['tsx', 'TSX'],
-]);
-
-const CodeTabsMap = new Map([['gradle', GradleTab]]);
-
-/**
- * Generic wrapper around Chakra's tab to make use in mdx easier.
- */
-const Tabs = (props: any) => {
- return (
- props.callback?.(index)}
- >
-
- {React.Children.map(props.children, (child: any) => {
- const TabComponent =
- CodeTabsMap.get(child.props.mdxType.toLowerCase()) ?? GenericTab;
- return (
-
- );
- })}
-
-
- {React.Children.map(props.children, (child: any) => {
- return (
-
- {child.props.children}
-
- );
- })}
-
-
- );
-};
-
-/**
- * Tabs specifically for plugin docs that only allow certain tabs
- */
-const PlatformTabs = (props: React.PropsWithChildren) => {
- const [searchParams, setSearchParams] = useSearchParams();
- const navigate = useNavigate();
-
- const children = React.Children.toArray(props.children).filter((c: any) =>
- CodeTabsNameMap.has(c.props.mdxType.toLowerCase()),
- );
-
- const langPrefIndex = children.findIndex(
- (c: any) => c.props.mdxType.toLowerCase() === searchParams.get("lang"),
- );
-
- const defaultTab = Math.max(langPrefIndex, 0);
-
- return (
- {
- const lang = (children[tabIndex] as any).props.mdxType.toLowerCase();
-
- setSearchParams(
- Object.fromEntries([...searchParams.entries(), ["lang", lang]]),
- );
- }}
- >
- {children}
-
- );
-};
-
-/**
- * Tab section for Content Authoring. This should include tsx and/or example JSON files.
- */
-const ContentTabs = (props: React.PropsWithChildren) => {
- const children = React.Children.toArray(props.children).filter((c: any) => {
- return ContentTabsNameMap.has(c.props.mdxType.toLowerCase());
- });
-
- return {children};
-};
-
-const langMap: Record = {
- js: "javascript",
- ts: "typescript",
-};
-
-/**
- * Code Block comopnent
- */
-const Code = (props: any) => {
- let lang = props.className?.split("-")[1];
- if (langMap[lang] !== undefined) {
- lang = langMap[lang];
- }
-
- return (
-
- {props.children.trim()}
-
- );
-};
-
-/**
- * Image Component
- */
-export const Img = (props: JSX.IntrinsicElements["img"]) => {
- const darkModeInvert = props.src?.includes("darkModeInvert");
- const darkModeOnly = props.src?.includes("darkModeOnly");
- const lightModeOnly = props.src?.includes("lightModeOnly");
-
- const { colorMode } = useColorMode();
-
- const filterStyles = useColorModeValue(
- undefined,
- "invert(80%) hue-rotate(180deg);",
- );
-
- if (
- (colorMode === "light" && darkModeOnly) ||
- (colorMode === "dark" && lightModeOnly)
- ) {
- return null;
- }
-
- return (
-
-
-
- );
-};
-
-/**
- * Normalize URL to conform to local path rules
- */
-export const useNormalizedUrl = (url: string) => {
- return url;
-
- // const router = useRouter();
-
- // if (!url.startsWith(".")) {
- // return url;
- // }
-
- // const ext = path.extname(url);
- // let withoutExt = url;
- // if (ext) {
- // withoutExt = path.join(path.dirname(url), path.basename(url, ext));
- // }
-
- // return path.join(path.dirname(router.pathname), withoutExt);
-};
-
-export const InlineCode = (props: JSX.IntrinsicElements["code"]) => {
- return (
-
- );
-};
-
-type ChakraAlertProps = React.PropsWithChildren<{
- status?: AlertStatus;
- title?: string;
- description?: string;
-}>
-
-export const Alert = (props: ChakraAlertProps) => {
- return (
-
-
-
- {props.title && {props.title}}
- {props.description && {props.description}}
- {props.children}
-
-
- );
-};
-
-
-/**
- * Anchor tab component wrapping Chakra's
- */
-const A = (props: JSX.IntrinsicElements["a"]) => {
- const { href, ...other } = props;
- return (
-
- );
-};
-
-export const MDXComponents: MDXProviderComponents = {
- h1: (props: any) => ,
- h2: (props: any) => ,
- h3: (props: any) => ,
- h4: (props: any) => ,
-
- p: (props: any) => ,
- ul: UnorderedList,
- ol: OrderedList,
- li: ListItem,
- img: Img,
- code: Code,
-
- a: A,
-
- Tabs,
-
- PlayerTeam,
-
- PlatformTabs,
-
- ContentTabs,
-
- table: Table,
- th: Th,
- tr: Tr,
- td: Td,
-
- inlineCode: InlineCode,
-
- Alert,
- AlertTitle,
- AlertDescription,
-};
diff --git a/docs/site/components/player-demo/PlayerDemo.tsx b/docs/site/components/player-demo/PlayerDemo.tsx
deleted file mode 100644
index 99b7c5410..000000000
--- a/docs/site/components/player-demo/PlayerDemo.tsx
+++ /dev/null
@@ -1,119 +0,0 @@
-import React from "react";
-import { ManagedPlayer, Flow, FlowManager } from "@player-ui/react";
-import { ReferenceAssetsPlugin } from "@player-ui/reference-assets-plugin-react";
-import "@player-ui/reference-assets-plugin-react/dist/index.css";
-import {
- Box,
- VStack,
- Flex,
- Spinner,
- Button,
- Heading,
- HStack,
- Stack,
-} from "@chakra-ui/react";
-import { CodeHighlight } from "../code-highlight";
-import { basicFlowManager } from "./sample-flows/sample-flow-manager";
-
-export const PlayerDemo = () => {
- const config = React.useMemo(
- () => ({
- plugins: [new ReferenceAssetsPlugin()],
- }),
- [],
- );
-
- const [completed, setCompleted] = React.useState(false);
-
- const [currentFlow, setCurrentFlow] = React.useState();
-
- const flowManager = React.useMemo(() => {
- return {
- next: async (prev) => {
- const resp = await basicFlowManager.next(prev);
-
- if (resp.done) {
- setCurrentFlow(undefined);
- } else {
- setCurrentFlow((resp as any).value);
- }
-
- return resp;
- },
- };
- }, [setCurrentFlow]);
-
- return (
-
-
-
- {currentFlow
- ? JSON.stringify(currentFlow.views?.map((a) => a.title), null, 2)
- : "Start again"}
-
-
-
-
-
- {completed && (
-
- Done!
-
-
- )}
- {!completed && (
- }>
- {
- setCompleted(true);
- }}
- />
-
- )}
-
-
-
- );
-};
diff --git a/docs/site/components/player-demo/sample-flows/flow-1.json b/docs/site/components/player-demo/sample-flows/flow-1.json
deleted file mode 100644
index 1af4a0bb4..000000000
--- a/docs/site/components/player-demo/sample-flows/flow-1.json
+++ /dev/null
@@ -1,118 +0,0 @@
-{
- "id": "flow-1",
- "views": [
- {
- "id": "view-1",
- "type": "info",
- "title": {
- "asset": {
- "id": "info-title",
- "type": "text",
- "value": "Welcome to Player"
- }
- },
- "primaryInfo": {
- "asset": {
- "id": "info-primary",
- "type": "collection",
- "values": [
- {
- "asset": {
- "id": "info-primary-1",
- "type": "text",
- "value": "This is some content inside of a Player view."
- }
- }
- ]
- }
- },
- "actions": [
- {
- "asset": {
- "id": "action-next",
- "type": "action",
- "value": "Next",
- "label": {
- "asset": {
- "id": "action-next-label",
- "type": "text",
- "value": "Next"
- }
- }
- }
- }
- ]
- },
- {
- "id": "view-2",
- "type": "info",
- "title": {
- "asset": {
- "id": "title",
- "type": "text",
- "value": "This is another page in the 1st flow."
- }
- },
- "actions": [
- {
- "asset": {
- "id": "action-back",
- "type": "action",
- "value": "Prev",
- "label": {
- "asset": {
- "id": "action-back-label",
- "type": "text",
- "value": "Back"
- }
- }
- }
- },
- {
- "asset": {
- "id": "action-next",
- "type": "action",
- "value": "Next",
- "label": {
- "asset": {
- "id": "action-next-label",
- "type": "text",
- "value": "Next"
- }
- }
- }
- }
- ]
- }
- ],
- "navigation": {
- "BEGIN": "FLOW_1",
- "FLOW_1": {
- "startState": "VIEW_1",
- "VIEW_1": {
- "state_type": "VIEW",
- "ref": "view-1",
- "transitions": {
- "Prev": "END_Back",
- "Next": "VIEW_2"
- }
- },
- "VIEW_2": {
- "state_type": "VIEW",
- "ref": "view-2",
- "transitions": {
- "Prev": "VIEW_1",
- "Next": "END_Done"
- }
- },
- "END_Back": {
- "state_type": "END",
- "outcome": "back"
- },
- "END_Done": {
- "state_type": "END",
- "outcome": "done"
- }
- }
- }
-}
diff --git a/docs/site/components/player-demo/sample-flows/flow-2.json b/docs/site/components/player-demo/sample-flows/flow-2.json
deleted file mode 100644
index c12c9b7b7..000000000
--- a/docs/site/components/player-demo/sample-flows/flow-2.json
+++ /dev/null
@@ -1,83 +0,0 @@
-{
- "id": "flow-2",
- "views": [
- {
- "id": "view-1",
- "type": "info",
- "title": {
- "asset": {
- "id": "info-title",
- "type": "text",
- "value": "This is the 2nd flow."
- }
- },
- "primaryInfo": {
- "asset": {
- "id": "info-primary",
- "type": "collection",
- "values": [
- {
- "asset": {
- "id": "info-primary-1",
- "type": "text",
- "value": "Note the delay between loading flows to emulate a network request/response"
- }
- }
- ]
- }
- },
- "actions": [
- {
- "asset": {
- "id": "action-back",
- "type": "action",
- "value": "Prev",
- "label": {
- "asset": {
- "id": "action-back-label",
- "type": "text",
- "value": "Back"
- }
- }
- }
- },
- {
- "asset": {
- "id": "action-next",
- "type": "action",
- "value": "Next",
- "label": {
- "asset": {
- "id": "action-next-label",
- "type": "text",
- "value": "Continue"
- }
- }
- }
- }
- ]
- }
- ],
- "navigation": {
- "BEGIN": "FLOW_1",
- "FLOW_1": {
- "startState": "VIEW_1",
- "VIEW_1": {
- "state_type": "VIEW",
- "ref": "view-1",
- "transitions": {
- "Prev": "END_Back",
- "Next": "END_Done"
- }
- },
- "END_Back": {
- "state_type": "END",
- "outcome": "back"
- },
- "END_Done": {
- "state_type": "END",
- "outcome": "done"
- }
- }
- }
-}
diff --git a/docs/site/components/player-demo/sample-flows/flow-3.json b/docs/site/components/player-demo/sample-flows/flow-3.json
deleted file mode 100644
index 827884c9e..000000000
--- a/docs/site/components/player-demo/sample-flows/flow-3.json
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "id": "flow-3",
- "views": [
- {
- "id": "view-1",
- "type": "info",
- "title": {
- "asset": {
- "id": "info-title",
- "type": "text",
- "value": "This is the 3nd and final flow in the series."
- }
- },
- "actions": [
- {
- "asset": {
- "id": "action-back",
- "type": "action",
- "value": "Prev",
- "label": {
- "asset": {
- "id": "action-back-label",
- "type": "text",
- "value": "Back"
- }
- }
- }
- },
- {
- "asset": {
- "id": "action-next",
- "type": "action",
- "value": "Next",
- "label": {
- "asset": {
- "id": "action-next-label",
- "type": "text",
- "value": "Finish"
- }
- }
- }
- }
- ]
- }
- ],
- "navigation": {
- "BEGIN": "FLOW_1",
- "FLOW_1": {
- "startState": "VIEW_1",
- "VIEW_1": {
- "state_type": "VIEW",
- "ref": "view-1",
- "transitions": {
- "Prev": "END_Back",
- "Next": "END_Done"
- }
- },
- "END_Back": {
- "state_type": "END",
- "outcome": "back"
- },
- "END_Done": {
- "state_type": "END",
- "outcome": "done"
- }
- }
- }
-}
diff --git a/docs/site/config/index.html b/docs/site/config/index.html
deleted file mode 100644
index 8e3fe6df2..000000000
--- a/docs/site/config/index.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- <%= htmlWebpackPlugin.options.title %>
-
-
-
diff --git a/docs/site/config/navigation.ts b/docs/site/config/navigation.ts
deleted file mode 100644
index 97837d1e5..000000000
--- a/docs/site/config/navigation.ts
+++ /dev/null
@@ -1,193 +0,0 @@
-import pluginNavData from "./plugin-nav-data.json";
-
-export const enum Platform {
- core = "core",
- react = "react",
- ios = "ios",
- android = "android",
-}
-
-export interface Route {
- title: string;
- path?: string;
- routes?: Array;
- metaData?: {
- platform?: Array;
- };
-}
-
-interface Navigation {
- routes: Array;
-}
-
-const navigation: Navigation = {
- routes: [
- {
- title: "Player",
- routes: [
- {
- title: "About",
- path: "/about",
- },
- {
- title: "Team",
- path: "/team",
- },
- {
- title: "FAQs",
- path: "/faqs",
- },
- {
- title: "Guides",
- routes: [
- {
- title: "Getting Started",
- path: "/getting-started",
- },
- {
- title: "Writing Plugins",
- path: "/writing-plugins",
- },
- {
- title: 'Plugin Implementation',
- path: '/plugin-implementation',
- },
- {
- title: 'Multi-Flow Experiences',
- path: '/guides/multi-flow-experiences',
- },
- {
- title: "Designing Semantic Assets",
- path: "/guides/designing-semantic-assets",
- },
- ],
- },
- {
- title: "Content",
- routes: [
- {
- title: "Overview",
- path: "/content",
- },
- {
- title: 'Navigation',
- path: '/content/navigation',
- },
- {
- title: 'Assets & Views',
- path: '/content/assets-views',
- },
- {
- title: "Data & Expressions",
- path: "/content/data-expressions",
- },
- {
- title: 'Schema',
- path: '/content/schema',
- },
- ],
- },
- {
- title: 'Authoring',
- routes: [
- {
- title: 'Overview',
- path: '/dsl',
- },
- {
- title: 'Views',
- path: '/dsl/views',
- },
- {
- title: 'Schema',
- path: '/dsl/schema',
- },
- {
- title: 'Plugins',
- path: '/dsl/plugins',
- },
- ],
- },
- {
- title: "Assets",
- routes: [
- {
- title: "Overview",
- path: "/assets",
- },
- {
- title: "Transforms",
- path: "/assets/transforms",
- },
- {
- title: "Reference Assets",
- path: "/assets/reference",
- },
- {
- title: "Custom Assets",
- path: "/assets/custom",
- },
- {
- title: 'DSL Components',
- path: '/assets/dsl',
- },
- ],
- },
- {
- title: "Tools",
- routes: [
- {
- title: "Storybook",
- path: "/tools/storybook",
- },
- {
- title: "CLI",
- path: "/tools/cli",
- },
- ],
- },
- {
- title: "XLR",
- routes: [
- {
- title: "Intro",
- path: "/xlr/intro",
- },
- {
- title: "Concepts",
- path: "/xlr/concepts",
- },
- {
- title: "Usage",
- path: "/xlr/usage",
- },
- ],
- },
- ],
- },
- {
- title: "Plugins",
- routes: pluginNavData.routes,
- },
- ],
-};
-
-export const PATH_TO_NAV = (() => {
- const pathMap = new Map();
-
- const expandRoutes = (route: Route, context: string[] = []) => {
- if (route.path) {
- pathMap.set(route.path, context);
- }
-
- route.routes?.forEach((nestedRoute) => {
- expandRoutes(nestedRoute, [...context, route.title]);
- });
- };
-
- navigation.routes.forEach((r) => expandRoutes(r));
-
- return pathMap;
-})();
-
-export default navigation;
diff --git a/docs/site/config/plugin-nav-data.json b/docs/site/config/plugin-nav-data.json
deleted file mode 100644
index 9ade02d5d..000000000
--- a/docs/site/config/plugin-nav-data.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "routes": []
-}
diff --git a/docs/site/config/search-index.json b/docs/site/config/search-index.json
deleted file mode 100644
index 0967ef424..000000000
--- a/docs/site/config/search-index.json
+++ /dev/null
@@ -1 +0,0 @@
-{}
diff --git a/docs/site/config/team.json b/docs/site/config/team.json
deleted file mode 100644
index e1405bf9a..000000000
--- a/docs/site/config/team.json
+++ /dev/null
@@ -1,52 +0,0 @@
-[
- {
- "name": "Adam Dierkens",
- "domain": ["React", "Core"],
- "avatar": "https://avatars.githubusercontent.com/u/13004162?v=4"
- },
- {
- "name": "Harris Borawski",
- "domain": ["iOS"],
- "avatar": "https://avatars.githubusercontent.com/u/1325154?v=4"
- },
- {
- "name": "Jeremiah Zucker",
- "domain": ["Android"],
- "avatar": "https://avatars.githubusercontent.com/u/9255651?&v=4"
- },
- {
- "name": "Ketan Reddy",
- "domain": ["Core", "Tools"],
- "avatar": "https://avatars.githubusercontent.com/u/8703262?v=4"
- },
- {
- "name": "Spencer Hamm",
- "domain": ["React", "Core"],
- "avatar": "https://avatars.githubusercontent.com/u/1043478?v=4"
- },
- {
- "name": "Tony Lin",
- "domain": ["Android"],
- "avatar": "https://avatars.githubusercontent.com/u/13474011?v=4"
- },
- {
- "name": "Rafael Campos",
- "domain": ["Tools"],
- "avatar": "https://avatars.githubusercontent.com/u/26394217?v=4"
- },
- {
- "name": "Marlon Ercillo",
- "domain": ["React"],
- "avatar": "https://avatars.githubusercontent.com/u/3643493?v=4"
- },
- {
- "name": "Alejandro Fimbres",
- "domain": ["Tools"],
- "avatar": "https://avatars.githubusercontent.com/u/9345943?v=4"
- },
- {
- "name": "Nancy Wu",
- "domain": ["iOS"],
- "avatar": "https://avatars.githubusercontent.com/u/66387473?v=4"
- }
-]
diff --git a/docs/site/package.json b/docs/site/package.json
index 474e32592..da1fd1292 100644
--- a/docs/site/package.json
+++ b/docs/site/package.json
@@ -1,11 +1,12 @@
{
- "name": "@player-ui/docs",
+ "name": "@player-ui/astro-docs",
"private": true,
"homepage": "https://player-ui.github.io",
"type": "module",
"dependencies": {
+ "@player-ui/player": "workspace:*",
"@player-ui/react": "workspace:*",
- "@player-ui/reference-assets-plugin-react": "workspace:*",
- "@player-ui/asset-provider-plugin-react": "workspace:*"
+ "@player-ui/reference-assets-plugin-components": "workspace:*",
+ "@player-ui/reference-assets-plugin-react": "workspace:*"
}
}
diff --git a/docs/site/pages/assets/transforms.mdx b/docs/site/pages/assets/transforms.mdx
deleted file mode 100644
index 0ae9c8209..000000000
--- a/docs/site/pages/assets/transforms.mdx
+++ /dev/null
@@ -1,33 +0,0 @@
----
-title: 'Transforms'
----
-
-# Assets and Transforms
-
-This guide will walk through a few of the core concepts of assets, transforms and how they come together with the UI to create an experience.
-
-You can read more about what an asset is [here](../content/assets-views). In short:
-
-> An asset is a generic term given to a semantic bit of information that we wish to convey to the user. Assets are the primitive elements that make up the content that players present as user experiences.
-
-For all intents and purposes, views are equivalent to assets for this guide.
-
-## Assets and the UI
-
-In general, the pipeline for user-content is something like:
-
-![Simple Asset Pipeline](/simple-diagram-asset.png?darkModeInvert)
-
-Player will do minimal processing of each asset in the tree, resolving [data in strings](../content/data-and-expressions), [applicability](../content/assets-views#applicability) and any other generic processing it can. The processed tree is then sent to the rendering layer, where it is turned into a native component on the system Player is running on.
-
-For simple Assets, like text, there's no need for any asset specific processing. The output of Player is enough to successfully render and display the content to the user.
-
-![Asset Without Transform](/no-transform.png?darkModeInvert)
-
-## Transforms
-
-When dealing with user interactions(`inputs`, `selections`) or some further data/communication is needed with Player, we expose a mechanism for individual assets to augment Player's processing with it's own custom data. By breaking this out into it's own discrete step (outside of the UI), we allow asset state to exist outside on an individual rendering, and thus sharable across platforms. These augmentations are processed through a stateless function called a transform.
-
-![Asset With Transform](/pipeline-with-transform.png?darkModeInvert)
-
-Transforms can be added through the [asset-transform](../plugins/asset-transform) plugin, and they run as part of the core player's reconciliation step. This improves performance, as the transforms are cached between updates to the view, and re-usable as they can be registered across platforms to share common logic for assets. You can refer to the [cross-platform](./cross-platform) guide on sharing Player logic across multiple platforms.
diff --git a/docs/site/pages/dsl/index.mdx b/docs/site/pages/dsl/index.mdx
deleted file mode 100644
index bf8036720..000000000
--- a/docs/site/pages/dsl/index.mdx
+++ /dev/null
@@ -1,172 +0,0 @@
----
-title: DSL Content Overview
----
-
-# TSX/JSX Content Authoring (Player DSL)
-
-While Player content _can_ be written directly in JSON, it's definitely not the preferable authoring format. To take advantage of existing developer tool-chains, Player provides a mechanism for authoring content in (J/T)SX as React components and simple TypeScript objects. The Player CLI can then be used to transpile the React tree into a JSON content.
-
-## DSL Benefits
-
-At a high level, the benefits to writing Player content in the DSL can be summarized by three key factors:
-
-#### Easier maintainability
-Simply put, DSL code more concise than its JSON equivalent. That means there is less code for you to have to maintain. Also, as its easier to read than JSON, when you do need to make updates to it, its much more wieldy to work with.
-
-#### Better development experience
-Since the DSL leverages a lot of standard TypeScript language features, most editors will offer quality of life features like typechecking, suggestions, and code generation. All of this is in service of shortening the feedback loop of writing content and ensuring it is what you intended for it.
-
-#### Easier to extend
-The DSL now offers a easily accessible programatic hook into Player content. This allows custom tooling to be created around your DSL integration much easier that before. Common patterns can be extracted into higher level compoennts, functions can be created to generate code, and code generation can be integrated into almost any process where relevant data is present.
-
-For a further explination on the benefits, see the DSL Benefits section in the [DSL Views](./views.mdx#dsl-benefits-in-views) and the [DSL Schema](./schema.mdx#dsl-benefit-in-schema)
-
-## Writing DSL Content
-
-In order to use the DSL to write content, your plugin library should ship a DSL component package. These will define the primitive _components_ to use to build up the tree. Authorship of these components is covered in the [Writing DSL Components](../assets/dsl) secton. The Player Reference Assets ship their own DSL Components via the `@player-ui/reference-assets-components` pacakge.
-
-In the examples below, we will use the Player Reference Assets Components.
-
-### Basic Setup
-
-To get started, you'll need the following dependencies in your `package.json`:
-
-```json
-{
- "dependencies": {
- "@player-tools/dsl": "0.4.1",
- "@player-tools/cli": "0.4.1",
- "@player-ui/reference-assets-components": "0.6.0",
- "@types/react": "17.0.39",
- "react": "17.0.2"
- }
-}
-```
-
-Next, you'll need to configure your environment for DSL Compilation and JSON validation. Below is a basic configuration that can be added in your `package.json`. For a more detailed explination and examples on further customization please refer to the [CLI](../tools/cli) section.
-
-```json
-{
- "player": {
- "dsl": {
- "src": "./src/main/tsx",
- "outDir": "./out"
- },
- "json": {
- "src": "./out/*.json"
- },
- }
-}
-```
-
-### Basic Format and File Layout
-
-By default, all files that contain a Player Flow should be exported as a `.tsx` file and the schema should be in a `.ts` file. For how to change this behavior, please refer to the [DSL Plugins](./plugins) section of the docs. Each of these files should contain a default export of their appropriate object. For example a file that exports a flow should look like the following:
-
-```tsx
-export default {
- id: 'my-flow',
- views: [....],
- navigation: {....}
-}
-```
-
-and a file that exports the schema should look like:
-
-```typescript
-const mySchema = {...}
-
-export default mySchema
-
-```
-
-### Navigation
-
-At this time the `navigation` section is a basic JS object. The `@player-ui/types` package provides typescript typings for this.
-
-```tsx
-import { Navigation } from '@player-ui/types';
-
-const navigation: Navigation = {
- BEGIN: 'Start',
- Start: {
- startState: 'VIEW_1',
- VIEW_1: {
- state_type: 'VIEW',
- ref: 'view-1',
- transitions: {
- '*': 'END_Done',
- },
- },
- END_Done: {
- state_type: 'END',
- outcome: 'done',
- },
- },
-};
-```
-
-One convenience feature is the auto injection of the the `ref` property for a `VIEW` type state if the corresponding view is a React tree.
-
-```tsx
-import { Navigation } from '@player-ui/types';
-
-const view = (
-
- Some value
-
- Some label
-
-
-);
-
-const navigation: Navigation = {
- BEGIN: 'Start',
- Start: {
- startState: 'VIEW_1',
- VIEW_1: {
- state_type: 'VIEW',
- ref: view,
- transitions: {
- '*': 'END_Done',
- },
- },
- END_Done: {
- state_type: 'END',
- outcome: 'done',
- },
- },
-};
-```
-
-_Note: The `Navigation` type we're importing here from the `@player-ui/types` package is different than the `Navigation` type from the `@player-tools/dsl` package. The former is the core definition for what the Navigation section of Player content is. The latter has specific replacements to take DSL constructs where normal objects would be defined._
-
-### Bindings and Expressions
-
-Both `binding` and `expression` in the JSX authoring leverages a tagged template, typically abbreviated as `b` and `e` respectively. In a similar fashion to using `css` or `graphql` in a JS file, this enables syntax-highlighting and validation of bindings and expressions within a JS file.
-
-```tsx
-import { binding as b, expression as e } from '@player-tools/dsl';
-
-const myBinding = b`foo.bar`;
-const myExpression = e`foo()`;
-```
-
-The binding and expression instances can also automatically dereference themselves when used inside of another string:
-
-```tsx
-const stringWithBinding = `Some text: ${myBinding}`; // 'Some text: {{foo.bar}}'
-const stringWithExp = `Some expr: ${myExpression}`; // 'Some expr: @[foo()]@'
-```
-
-### View
-
-Please refer to the [Views](../dsl/views) section for a detailed overview of how to write DSL Views
-
-### Schema
-
-Please refer to the [Schema](../dsl/schema) section for a detailed overview of how to write DSL Schemas
-
-## Compiling DSL Content
-
-Once your DSL content is authored, you can use the Player CLI to compile and validate your content. For documentation on this functionality, please refer to the [Player CLI](../tools/cli) section
\ No newline at end of file
diff --git a/docs/site/pages/dsl/plugins.mdx b/docs/site/pages/dsl/plugins.mdx
deleted file mode 100644
index 1e81c7058..000000000
--- a/docs/site/pages/dsl/plugins.mdx
+++ /dev/null
@@ -1,46 +0,0 @@
----
-title: DSL Plugins
----
-
-# DSl Plugins
-
-Much like the rest of Player, DSL compilation supports plugins that can influce how content gets compiled and generated. DSL Plugins are a subset of CLI Plugins that use either the hooks available on the CLI itself or on the DSL compiler instance created by the CLI. This section will cover the hooks that are available for use and why you might want to tap them.
-
-## CLI Hooks
-
-The `createCompilerContext` function available to plugins that extend the `PlayerCLIPlugin` class gives access to the `CompilationContext` instance. This class manages the context around DSL compilation and exposes two related hooks.
-
-### `identifyContentType`
-
-The `identifyContentType` hooks's purpose is to allow plugins to inject custom behavior around detecting what kind of file is being compiled. By default there are three types of content the CLI is aware of (`view`, `flow`, and `schema`). Its methods for detecting which kind of content is contained within a file is very rudimentary (the logic can be found [here](https://github.com/player-ui/tools/blob/main/language/dsl/src/compiler/utils.ts#L5)). In order to allow desired convention or orchestrate the compilation of custom file types, this hook provides a mechanism for allowing that custom logic to be injected. The result of this hook is used in the next hook
-
-### `compileContent`
-
-The `compileContent` hook's purpose is to allow the custom compilation logic for any identified file type. As it is an `AsyncSeriesBailHook` it will take the first result returned from a tap who was able to return a result for the compilation for the given file of the identified type. In the case where no external logic is added, the hook will attempt to compile any of its known content types with the built in compiler instance.
-
-## Compilation Hooks
-
-The CLI will initialize an instance of the `DSLCompiler` and provide a reference to it via the `onCreateDSLCompiler` function available to plugins that extend the `PlayerCLIPlugin` class. On the compiler itself, the following hook are available to modify the behavior of how DSL content is compiled.
-
-### `preProcessFlow`
-_Note: Only called for `view` or `flow` content_
-
-This hook allows transformations on the content before it is compiled. This enables the injection of additonal data or resolving any integration specific convention into something that may be understood by the compiler. This hook can also be used to collate information on what is being compiled for use later.
-
-### `postProcessFlow`
-_Note: Only called for `view` or `flow` content_
-
-This hook allows transformations on the content after it is compiled. This allows modifications to the compiled content which in some cases may be preferable as manipulating JSON may be easier than a React Tree.
-
-### `schemaGenerator`
-
-This hook gives access to the internal `SchemaGenerator` object which is responsible for compiling the schema. On this generator there are the following hooks.
-
-#### `createSchemaNode`
-
-This hook allows custom logic for processing schema nodes as they are generated. This enables arbitrary properties to be statically or dynamically added based on the authored schema node. One potential usecase of this is to allow integration specific semantic conventions to be defined and injected into the final schema. For example, the presence of a specific `Symbol` might mean that a property needs to be injected or even that the schema tree from this point on needs to be modified.
-
-
-### `onEnd`
-
-This hook is called to signal that the compilation of all files has been completed. This allows any post processing on the output as a whole to take place as a part of the build process. This may include actions like moving or bundling the compilation results or writing new files based on information collected via other hooks on the files that were processed.
\ No newline at end of file
diff --git a/docs/site/pages/dsl/schema.mdx b/docs/site/pages/dsl/schema.mdx
deleted file mode 100644
index 0682e86d3..000000000
--- a/docs/site/pages/dsl/schema.mdx
+++ /dev/null
@@ -1,308 +0,0 @@
----
-title: Writing DSL Schemas
----
-
-# Basic Schema
-
-To author a schema object you should first start by constructing a standard typescript object where the nested paths correlate to the paths on your desired schema. When compiled to the final Player `Schema` object, the intermediate types and ROOT elements will automatically be constructed. A basic example would be:
-
-```typescript
-export default {
- foo: {
- bar: {
- baz: {...}
- faz: {...}
- }
- }
-}
-```
-
-which correlates to a schema of:
-
-```json
-{
- "ROOT": {
- "foo": {
- "type": "fooType"
- }
- },
- "fooType": {
- "bar": {
- "type": "barType"
- }
- },
- "barType": {
- "baz": {...},
- "faz": {...}
- }
-}
-```
-
-## Arrays
-
-A single object array can be used to indicate an array type, for example:
-
-```typescript
-export default {
- foo: [
- {
- bar: {...}
- }
- ]
-}
-```
-
-will generate the schema:
-
-```json
-{
- "ROOT": {
- "foo": {
- "type": "fooType",
- "isArray": true
- }
- },
- "fooType": {
- "bar": {
- "type": "barType"
- }
- },
- "barType": {
- "baz": {...},
- "faz": {...}
- }
-}
-```
-
-## Changing the Name of a Generated Type
-
-To change the name of the generated type at any point in the tree, import the `SchemaTypeName` symbol from the `@player-tools/dsl` and use it as a key on the object whos name you want to change:
-
-```typescript
-import { SchemaTypeName } from "@player-tools/dsl"
-export default {
- foo: {
- bar: {
- [SchemaTypeName]: "buzz",
- baz: {...}
- faz: {...}
- }
- }
-}
-```
-
-will generate the schema:
-
-```json
-{
- "ROOT": {
- "foo": {
- "type": "fooType",
- "isArray": true
- }
- },
- "fooType": {
- "buzz": {
- "type": "buzzType"
- }
- },
- "buzzType": {
- "baz": {
- "type": ""
- },
- "faz": {
- "type": ""
- }
- }
-}
-```
-
-# Defining Data Types
-
-The leaf nodes of the schema will need some concrete definition of what data exists at that point of the schema. There are two ways to provide this data.
-
-## Data Refs
-
-The `@player-ui/common-types-plugin` package exposes the types it provides to Player when used and _references_ to those types as well. Using these `Language.DataTypeRef` values you can indicate what the data type will be at that node and that it will be a type explicitly defined in Player so no additional information needs to be provided (e.g. validations nor formats) as at runtime it will use the type loaded into Player by the plugin.
-
-It is recommended that if your player integration loads additional types, to export similar references to those types to make authorship easier.
-
-##### Local Data Types
-
-Sometimes you need to define specific data types that extend existing types for certain pieces of data in a schema, whether that be for specific validations, formatting or both. In this case, in your DSL project you can define an object of type `Schema.DataType` and provide that value to a leaf node. That will indicate that this unique type needs to be included in its entirety to Player as it has information not already contained in Player.
-
-##### What that Looks Like
-
-Using our previous example we can fill in the values with some types now to look like this in the ts object:
-
-```typescript
-import { dataTypes } from '@player-ui/common-types-plugin';
-import type { Schema } from '@player-ui/types';
-
-const mycustombooleantype = {
- type: "BooleanType",
- validation: [
- {
- type: 'oneOf',
- message: 'Value has to be true or false',
- options: [true, false],
- },
- ],
-} satisfies Schema.DataType
-
-const mySchema = {
- foo: {
- bar: {
- baz: dataTypes.BooleanTypeRef
- faz: mycustombooleantype
- }
- }
-}
-
-export default mySchema
-```
-
-and like this in the final schema:
-
-```json
-{
- "ROOT":{
- "foo":{
- "type": "fooType"
- }
- },
- "fooType":{
- "bar": {
- "type":"barType"
- }
- },
- "barType":{
- "baz":{
- "type": "BooleanType"
- },
- "faz":{
- "type": "BooleanType",
- "validation": [
- {
- "type": "oneOf",
- "message": "Value has to be true or false",
- "options": [true, false],
- },
- ],
- }
- }
-}
-```
-
-# DSLSchema Type
-
-A `DSLSchema` Type is provided in order be able to customize a set of the acceptable data types and validator functions to be used for authoring the DSL data schema in your workspace. This is useful as it allows content authors to get realtime feedback on their data schema. It can catch any structural issues that may produce an invalid schema at compile time or produce a schema that uses functionality thats not available at runtime.
-
-_Note: A ready-to-use DSLSchema type is shipped with `@player-ui/reference-assets-components`. This type is predefined with the `DataType` and `ValidatorFunction` references inferred from the `@player-ui/common-types-plugin`. Next, you'll be presented the steps in its creation for reference._
-
-The first step to fill in the `DSLSchema` type with your integration specific values is importing the `DSLSchema` type and the relevant helper types and utilities from `@player-tools/dsl`. For this example we are importing the `@player-ui/common-types-plugin` in order to use its data types and validators. Our first step is to generate the `DataType` and `ValidatorFunction` object types and references:
-
-```typescript
-import {
- DSLSchema,
- DataTypeReference
- DataTypeRefs,
- ValidatorFunctionRefs,
- getObjectReferences
-} from "@player-tools/dsl"
-import {
- dataTypes as commonDataTypes,
- validators as commonValidators
-} from "@player-ui/common-types-plugin";
-
-/** Abstracting the types from commonDataTypes to be passed as generic to the DataTypeRefs type for dynamically generating the data type reference Types */
-type myCommonDataTypesRefs = DataTypeRefs
-
-/** Using getObjectReferences helper to generate the actual data type references to be used in your schema by passing inferred types from commonDataTypes and myCommonDataTypesRefs */
-export const dataRefs = getObjectReferences(
- coreDataSet
-);
-```
-
-We'll proceed generating the validation function types:
-
-```typescript
-/** Abstracting types from coreValidators and using as generic of ValidatorFunctionRefs for dynamically generating the data validation function reference Types */
-type commonValidatorRefs = ValidatorFunctionRefs
-```
-
-The final step is to provide the data Types set and validator function reference Types as generics for the `DataTypeReference` type which is the sole generic type passed into the `DSLSchema` instance:
-```typescript
-type CommonDSLSchema = DSLSchema<
- DataTypeReference
->
-```
-
-Finally, this is how to use the custom schema type to type check your schema. By adding the `satisfies` keyword followed by your `DSLSchema` generated type, your editor's LSP will show if there is anything not compliant with the data types and validation functions you defined in the schema:
-
-```typescript
-import { CommonDSLSchema, dataRefs } from "./MyTypes"
-
-const { BooleanTypeRef } = dataRefs
-
-const exampleSchema = {
- myDataSet = {
- /** Simply using the BooleanTypeReference to define "firstPath" type to Boolean */
- firstPath: BooleanTypeRef
- secondPath: {
- /** For adding custom validation for "secondPath", define an object definition with the data "type" property, which is "TextType" for this example */
- type: "TextType",
- /** In the validation array open another object definition specifying the use of the "required" validator with the "type" property, with a custom "message" value */
- validation: [
- {
- type: "required",
- message: "This field is required"
- }
- ]
- }
- }
-} satisfies CommonDSLSchema
-```
-
-_Note: The `satisfies` Typescript operator is used instead of type assignment (`exampleSchema:DSLSChema`), because `satisfies` doesn't lose the inferred type of your value by changing and broadening the type unlike using assignment, it simply type-checks, creating localised feedback if anything is incorrect._
-
-
-# Using the Schema Object in JSX/TSX Content
-
-As the schema is now a TypeScript obejct, you can now directly reference the schema anywhere in content. The `makeBindingsForObject()` function takes your schema object and constructs the bindings opaquely within the object. This allows the use of the native path in your authored content and for the actual underlying binding to be used when the content is compiled. Additionally, as the underlying bindings are exposed, can you can use the native object path with functions like `.toString()`, `.toValue()`, and `toRefString()` like you could with regular string template bindings.
-
-```jsx
-import { makeBindingsForObject } from '@player-tools/dsl';
-import { mySchema } from './schema'
-
-const schema = makeBindingsForObject(mySchema)
-
-const baz = schema.foo.bar.baz
-
-const view = (
-
-
-
- The current value is {baz.toString()}
-
-
-
-)
-
-const navigation = {...}
-
-export default {
- id: "example",
- views: [view],
- navigation,
-}
-```
-
-# DSL Benefits in Schema
-Player's schema has a few issues that makes it both hard to write and very susceptible to experience breaking mistakes. The DSL Schema aims to mitigate all of these pitfalls.
-
-## Format
-The flattened nature of Player's schema makes it confusing to write for content authors new to Player and tedius to write for more experienced content authors. By allowing the schema to be represented in a tree format, the schema is both easier to write and more closely resembles the shape that the data will take in the data model.
-
-## Ease of Use
-The biggest quality of life improvement the DSL schema brings is that the schema object can be directly used in content. This almost completely eliminates the positiblity of mistyping a schema path leading to runtime errors and massively reduces how verbose content needs to be. Additionally, with plugins able to export references to the data types and validation functions they export, content can now directly reference those artifacts further reducing the possibility of producing invalid content. Lastly, given the number of features that are available in the schema, it can be overwhelming to remember what can/should be used where. By making the schema a normal TypeScript object and assigning it the proper type, content authors are given autocomplete suggestions and a cursory level of validation in their development environment while they are writing their schema.
diff --git a/docs/site/pages/dsl/views.mdx b/docs/site/pages/dsl/views.mdx
deleted file mode 100644
index 13457d727..000000000
--- a/docs/site/pages/dsl/views.mdx
+++ /dev/null
@@ -1,133 +0,0 @@
----
-title: Writing DSL Views
----
-
-# Overview
-Writing assets or views is as simple as creating a React element using your base DSL components:
-
-```tsx
-import React from 'react';
-import { Input, Text, Collection } from '@player-ui/reference-assets-components';
-
-const view = (
-
- Some value
-
- Some label
-
-
-);
-```
-
-When compiled, this would produce the following JSON.
-
-```json
-{
- "id": "root",
- "type": "collection",
- "values": [
- {
- "asset": {
- "id": "root-values-1",
- "type": "text",
- "value": "Some value"
- }
- },
- {
- "asset": {
- "id": "root-values-2",
- "type": "input",
- "label": {
- "asset": {
- "id": "root-values-2-label",
- "type": "text",
- "value": "Some label"
- }
- }
- }
- }
- ]
-}
-```
-
-Not only is the source DSL content a fraction of the output object's size (making it easier to read and maintain) as the base components use the same TypeScript types as the assets themselves, you will receive in editor suggestions and type checks as you author your content.
-
-# View Concepts in DSL
-
-## Templates
-
-Templates are included via the `@player-tools/dsl` package. This can be used in any asset slot:
-
-```tsx
-import React from 'react';
-import { dataTypes } from '@player-ui/common-types-plugin';
-import { makeBindingsForObject, Template } from '@player-tools/dsl';
-
-const schema = {
- foo: [{
- bar: dataTypes.StringType,
- }],
-};
-
-const bindings = makeBindingsForObject(schema);
-
-
-
-
- The current item is: {bindings.foo._index_.bar}
-
-
-
-```
-
-Templates can be nested within one another, and the auto-id generation will handle adding the `_index_` information to any generated `id`.
-
-## Switches
-
-The `@player-tools/dsl` module also includes support for _static_ and _dynamic_ switches.
-
-Use the `isDynamic` flag to denote this should be a `dynamicSwitch` instead of a `staticSwitch`:
-
-```tsx
-import React from 'react';
-import { Switch } from '@player-tools/dsl';
-
-
-
-
-
- Text 1
-
-
- Text 1
-
-
-
-
-```
-
-# DSL Benefits in Views
-
-## IDs
-
-Any asset can accept an `id` property, however automatic ID creation is supported out of the box by the base `Asset` component and it's generation behavior can be further customized via your component's implementation.
-
-## Collection/Text Creation
-
-In the event that an asset object is expected, but a `string` or `number` is found, Player will attempt to automatically create a text node, provided the asset-library has a text-asset-factory configured.
-
-Similarly, if a single asset is expected but a list of them is found instead, Player will attempt to create a _collection_ asset provided the library has the proper configuration set.
-
-## Meta Components
-
-As DSL components are React component, they can be composed into reusable building blocks to simplify and abstract away common UI patterns. By centralizing these patterns, code duplication can be minimized and updates across multiple sets of content can be simplified. These composed components don't just have to be built on top of the base set of DSL components, DSL components themselves can offer common shortcuts for behavior. For example, if we wanted to offer an out of the box `Action` component that could be used as a `Next` action asset, we could export the following from the DSL components library.
-
-```tsx
-import React from 'react';
-
-Action.Next = () => (
-
- Continue
-
-);
-```
\ No newline at end of file
diff --git a/docs/site/pages/global.css b/docs/site/pages/global.css
deleted file mode 100644
index 878cf03c9..000000000
--- a/docs/site/pages/global.css
+++ /dev/null
@@ -1,9 +0,0 @@
-@font-face {
- font-family: "Virgil";
- src: url("https://excalidraw.com/Virgil.woff2");
-}
-
-@font-face {
- font-family: "Cascadia";
- src: url("https://excalidraw.com/Cascadia.woff2");
-}
\ No newline at end of file
diff --git a/docs/site/pages/index.tsx b/docs/site/pages/index.tsx
deleted file mode 100644
index c7d834748..000000000
--- a/docs/site/pages/index.tsx
+++ /dev/null
@@ -1,171 +0,0 @@
-import React from "react";
-import { Link } from "react-router-dom";
-
-import {
- ButtonGroup,
- VStack,
- Heading,
- Button,
- Image,
- Box,
- Text,
- Link as CLink,
- Divider,
- Container,
- HStack,
- SimpleGrid,
- useColorModeValue,
-} from "@chakra-ui/react";
-import { EditIcon, LinkIcon, UnlockIcon, SettingsIcon } from "@chakra-ui/icons";
-import { Img } from "../components/mdx-components";
-import { GitHubButton } from "../components/Navigation";
-import { ColorSchemeSwitch } from "../components/ColorSchemeSwitch";
-import { withBasePrefix } from "../components/Image";
-import { PlayerDemo } from "../components/player-demo/PlayerDemo";
-
-const TagLine = (props: {
- title: React.ReactNode;
- description: React.ReactNode;
- // eslint-disable-next-line react/no-unused-prop-types
- icon: typeof EditIcon;
-}) => {
- return (
-
-
-
-
-
- {props.title}
-
- {props.description}
-
-
-
- );
-};
-
-const TagLines = () => {
- return (
-
-
-
- Player works seamlessly with your existing UI components to fit
- application. Define your own patterns through{" "}
-
- assets
- {" "}
- and render them exactly as your designers intended.
-
- }
- />
-
- Need to figure out where go next? Chaining multiple pages together
- with Player is a breeze. Check out the{" "}
-
- docs
- {" "}
- for more details.
-
- }
- />
-
- Player is designed from the ground up with plugins in mind.{" "}
-
- Read more
- {" "}
- about the 20+ provided plugins, or how to write your own.
-
- }
- />
-
- );
-};
-
-const Banner = () => {
- const logoSrc = useColorModeValue(
- withBasePrefix("/logo/logo-light-large.png"),
- withBasePrefix("/logo/logo-dark-large.png"),
- );
-
- return (
-
-
-
- A cross-platform semantic rendering engine
-
-
- );
-};
-
-const Home = () => {
- return (
-
- {/*
- Player
- */}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- See it in action
-
-
-
- );
-};
-
-export default Home;
diff --git a/docs/site/pages/other.mdx b/docs/site/pages/other.mdx
deleted file mode 100644
index 50d225a20..000000000
--- a/docs/site/pages/other.mdx
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-# Other
-
-Test things
-
-
-
\ No newline at end of file
diff --git a/docs/site/pages/plugins/index.mdx b/docs/site/pages/plugins/index.mdx
deleted file mode 100644
index 010ea8d8f..000000000
--- a/docs/site/pages/plugins/index.mdx
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: Plugins
----
-
-# Plugins
-
-Plugins are one of the main ways to customize Player to suite individual use-cases.
-Internally they allow access to many of the core sub-systems, which can add features, configuration, or custom behaviors.
-
-![Plugins Overview Diagram](/plugin_overview.png?darkModeInvert)
-
-The scope of what a plugin is capable of is pretty broad, but are typically broken down into smaller reusable modules. Some are more end-user focused ([Common Expression Plugin](../plugins/common-expressions) and [Common Types Plugin](../plugins/common-types)) while others are more relavant for other plugin developers ([Expression Plugin](../plugins/expression) and [Types Provider Plugin](../plugins/types-provider))
diff --git a/docs/site/plugins/md-layout-loader.cjs b/docs/site/plugins/md-layout-loader.cjs
deleted file mode 100644
index 951b28783..000000000
--- a/docs/site/plugins/md-layout-loader.cjs
+++ /dev/null
@@ -1,47 +0,0 @@
-const path = require("path");
-const fm = require("gray-matter");
-const slugger = require("github-slugger");
-const removeMarkdown = require("remove-markdown");
-
-// https://github.com/chakra-ui/chakra-ui-docs/blob/main/src/utils/mdx-utils.ts
-function getTableOfContents(mdxContent) {
- const regexp = new RegExp(/^(#+\s)(.*)\n/, "gm");
- const headings = [...mdxContent.matchAll(regexp)];
- let tableOfContents = [];
-
- if (headings.length) {
- tableOfContents = headings.map((heading) => {
- const headingText = removeMarkdown(heading[2].trim());
- const headingType = heading[1].trim().length;
- const headingLink = slugger.slug(headingText, false);
-
- return {
- text: headingText,
- id: headingLink,
- level: headingType,
- };
- });
- }
-
- return tableOfContents;
-}
-
-module.exports = async function (src) {
- const callback = this.async();
- const { data, content } = fm(src);
-
- const compDir = path.relative(
- this.context,
- path.join(__dirname, "..", "components", "Layout", `MDXPageLayout`),
- );
-
- const code = `
-import withLayout from '${compDir}';
-export default withLayout(${JSON.stringify({
- ...data,
- tableOfContents: getTableOfContents(content),
- })})
-${content}`;
-
- return callback(null, code);
-};
diff --git a/docs/site/plugins/mdx-link-append-loader.cjs b/docs/site/plugins/mdx-link-append-loader.cjs
deleted file mode 100644
index 9279f0c66..000000000
--- a/docs/site/plugins/mdx-link-append-loader.cjs
+++ /dev/null
@@ -1,9 +0,0 @@
-const path = require("path");
-
-module.exports = function (source) {
- const filePath = this.resourcePath;
- const rootDir = this.rootContext;
- const relativePath = path.relative(rootDir, filePath);
- const newContent = `${source}\n\n---\n\n[Help to improve this page](https://github.dev/player-ui/player/blob/main/docs/site/${relativePath})`;
- return newContent;
-};
diff --git a/docs/site/plugins/mdx-link-append-loader.js b/docs/site/plugins/mdx-link-append-loader.js
deleted file mode 100644
index f27e598b5..000000000
--- a/docs/site/plugins/mdx-link-append-loader.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const path = require('path');
-
-module.exports = function (source) {
- const filePath = this.resourcePath;
- const rootDir = this.rootContext;
- const relativePath = path.relative(rootDir, filePath);
- const newContent = `${source}\n\n---\n\n[Help to improve this page](https://github.dev/player-ui/player/blob/main/docs/site/${relativePath})`;
- return newContent;
-};
diff --git a/docs/site/plugins/plugin-nav-generator.cjs b/docs/site/plugins/plugin-nav-generator.cjs
deleted file mode 100644
index 0df36e4bf..000000000
--- a/docs/site/plugins/plugin-nav-generator.cjs
+++ /dev/null
@@ -1,66 +0,0 @@
-const path = require("path");
-const fm = require("gray-matter");
-const globby = require("globby");
-const fs = require("fs/promises");
-
-const pluginsDir = path.join(__dirname, "..", "pages", "plugins");
-const exts = ["md", "mdx"];
-
-const platformOrder = ["core", "react", "ios", "android"];
-
-const cleanPlatforms = (platforms) =>
- (platforms?.toLowerCase().split(",") ?? [])
- .map((a) => a.trim())
- .sort((a, b) => platformOrder.indexOf(a) - platformOrder.indexOf(b));
-
-const genPath = (filepath) => path.basename(filepath).split(".")[0];
-
-const getPluginRoutes = async () => {
- const pluginRoutes = [
- {
- title: "Overview",
- path: "/plugins",
- },
- ];
-
- const matches = exts.map((e) => path.join(pluginsDir, "**", `*.${e}`));
- const plugins = await globby(matches);
-
- await Promise.all(
- plugins
- .filter((page) => !page.includes("index.md"))
- .map(async (page) => {
- const pageContents = await fs.readFile(page, "utf-8");
- const { data } = fm(pageContents);
-
- const route = {
- title: data.title,
- path: `/plugins/${genPath(page)}`,
- metaData: {
- platform: cleanPlatforms(data.platform),
- },
- };
-
- pluginRoutes.push(route);
- }),
- );
-
- return {
- routes: pluginRoutes.sort((a, b) => (a.path > b.path ? 1 : -1)),
- };
-};
-
-module.exports = async function () {
- const callback = this.async();
-
- try {
- const code = JSON.stringify(await getPluginRoutes());
-
- return callback(null, code);
- } catch (e) {
- console.error(e);
- return callback(e, null);
- }
-};
-
-module.exports.getPluginRoutes = getPluginRoutes;
diff --git a/docs/site/plugins/search-index-loader.cjs b/docs/site/plugins/search-index-loader.cjs
deleted file mode 100644
index ee22bfa20..000000000
--- a/docs/site/plugins/search-index-loader.cjs
+++ /dev/null
@@ -1,84 +0,0 @@
-const path = require('path');
-const fm = require('gray-matter');
-const slugger = require('github-slugger');
-const removeMarkdown = require('remove-markdown');
-const globby = require('globby');
-const fs = require('fs/promises');
-
-const pagesDir = path.join(__dirname, '..', 'pages');
-const exts = ['md', 'mdx'];
-
-const getLinkForPath = (p) => {
- const dirName = path.dirname(p);
- const baseName = path.basename(p, path.extname(p))
-
- return baseName === 'index' ? `/${dirName}` : `/${dirName}/${baseName}`
-}
-
-const withHeading = (p, heading) => heading ? `${p}#${heading}` : p
-
-
-const splitContentByHeadings = (title, contents, basePath) => {
- const regexp = new RegExp(/^(#+\s)(.*)\n/, 'gm');
- const headings = [...contents.matchAll(regexp)];
- const matches = {};
-
- if (!contents) {
- return matches;
- }
-
- let workingContentString = contents;
- let workingHeading;
-
- headings.forEach(heading => {
- if (!workingContentString) {
- return;
- }
-
- // Remove everything from workingContentString until we hit this heading
- const [contentsBeforeMatch, contentsAfterMatch] = workingContentString.split(heading[0])
-
- const result = {
- path: withHeading(basePath, slugger.slug(workingHeading, false)),
- content: [workingHeading, removeMarkdown(contentsBeforeMatch)].join('\n'),
- header: workingHeading,
- title,
- }
-
- matches[result.path] = result;
-
- workingContentString = contentsAfterMatch;
- workingHeading = removeMarkdown(heading[2]).trim();
- })
-
- return matches;
-}
-
-module.exports = async function () {
-
- const callback = this.async();
-
- try {
- let searchIndex = {};
-
- const matches = exts.map(e => path.join(pagesDir, '**', `*.${e}`));
- const pages = await globby(matches);
-
- await Promise.all(pages.map(async page => {
- const pageContents = await fs.readFile(page, 'utf-8');
- const pageRef = getLinkForPath(path.relative(pagesDir, page));
- const { data, content } = fm(pageContents);
-
- searchIndex = {
- ...searchIndex,
- ...splitContentByHeadings(data.title, content, pageRef)
- }
- }))
-
-
- return callback(null, JSON.stringify(searchIndex, null, 2));
- } catch (e) {
- console.error(e)
- return callback(e, null);
- }
-}
\ No newline at end of file
diff --git a/docs/site/public/android-chrome-192x192.png b/docs/site/public/android-chrome-192x192.png
new file mode 100644
index 000000000..039910996
Binary files /dev/null and b/docs/site/public/android-chrome-192x192.png differ
diff --git a/docs/site/public/android-chrome-256x256.png b/docs/site/public/android-chrome-256x256.png
new file mode 100644
index 000000000..c3a74b7cf
Binary files /dev/null and b/docs/site/public/android-chrome-256x256.png differ
diff --git a/docs/site/public/apple-touch-icon.png b/docs/site/public/apple-touch-icon.png
new file mode 100644
index 000000000..a6819842b
Binary files /dev/null and b/docs/site/public/apple-touch-icon.png differ
diff --git a/docs/site/public/browserconfig.xml b/docs/site/public/browserconfig.xml
new file mode 100644
index 000000000..b3930d0f0
--- /dev/null
+++ b/docs/site/public/browserconfig.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+ #da532c
+
+
+
diff --git a/docs/site/public/favicon-16x16.png b/docs/site/public/favicon-16x16.png
new file mode 100644
index 000000000..a50c8c9f2
Binary files /dev/null and b/docs/site/public/favicon-16x16.png differ
diff --git a/docs/site/public/favicon-32x32.png b/docs/site/public/favicon-32x32.png
new file mode 100644
index 000000000..f7787669f
Binary files /dev/null and b/docs/site/public/favicon-32x32.png differ
diff --git a/docs/site/public/favicon.ico b/docs/site/public/favicon.ico
new file mode 100644
index 000000000..c7e06e122
Binary files /dev/null and b/docs/site/public/favicon.ico differ
diff --git a/docs/site/public/mstile-150x150.png b/docs/site/public/mstile-150x150.png
new file mode 100644
index 000000000..cd315698e
Binary files /dev/null and b/docs/site/public/mstile-150x150.png differ
diff --git a/docs/site/public/platform_diagram_dark_mode.png b/docs/site/public/platform_diagram_dark_mode.png
deleted file mode 100644
index d29b520b8..000000000
Binary files a/docs/site/public/platform_diagram_dark_mode.png and /dev/null differ
diff --git a/docs/site/public/safari-pinned-tab.svg b/docs/site/public/safari-pinned-tab.svg
new file mode 100644
index 000000000..dedab3a05
--- /dev/null
+++ b/docs/site/public/safari-pinned-tab.svg
@@ -0,0 +1,39 @@
+
+
+
diff --git a/docs/site/public/site.webmanifest b/docs/site/public/site.webmanifest
new file mode 100644
index 000000000..de65106f4
--- /dev/null
+++ b/docs/site/public/site.webmanifest
@@ -0,0 +1,19 @@
+{
+ "name": "",
+ "short_name": "",
+ "icons": [
+ {
+ "src": "/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/android-chrome-256x256.png",
+ "sizes": "256x256",
+ "type": "image/png"
+ }
+ ],
+ "theme_color": "#ffffff",
+ "background_color": "#ffffff",
+ "display": "standalone"
+}
diff --git a/docs/site/public/asset-parts.png b/docs/site/src/assets/asset-parts.png
similarity index 100%
rename from docs/site/public/asset-parts.png
rename to docs/site/src/assets/asset-parts.png
diff --git a/docs/site/public/flow-manager.png b/docs/site/src/assets/flow-manager.png
similarity index 100%
rename from docs/site/public/flow-manager.png
rename to docs/site/src/assets/flow-manager.png
diff --git a/docs/site/public/logo/logo-dark-large.png b/docs/site/src/assets/logo/logo-dark-large.png
similarity index 100%
rename from docs/site/public/logo/logo-dark-large.png
rename to docs/site/src/assets/logo/logo-dark-large.png
diff --git a/docs/site/public/logo/logo-dark-small.png b/docs/site/src/assets/logo/logo-dark-small.png
similarity index 100%
rename from docs/site/public/logo/logo-dark-small.png
rename to docs/site/src/assets/logo/logo-dark-small.png
diff --git a/docs/site/public/logo/logo-light-large.png b/docs/site/src/assets/logo/logo-light-large.png
similarity index 100%
rename from docs/site/public/logo/logo-light-large.png
rename to docs/site/src/assets/logo/logo-light-large.png
diff --git a/docs/site/public/logo/logo-light-small.png b/docs/site/src/assets/logo/logo-light-small.png
similarity index 100%
rename from docs/site/public/logo/logo-light-small.png
rename to docs/site/src/assets/logo/logo-light-small.png
diff --git a/docs/site/public/metrics-timing.png b/docs/site/src/assets/metrics-timing.png
similarity index 100%
rename from docs/site/public/metrics-timing.png
rename to docs/site/src/assets/metrics-timing.png
diff --git a/docs/site/public/metrics-timing.svg b/docs/site/src/assets/metrics-timing.svg
similarity index 100%
rename from docs/site/public/metrics-timing.svg
rename to docs/site/src/assets/metrics-timing.svg
diff --git a/docs/site/public/no-transform.png b/docs/site/src/assets/no-transform.png
similarity index 100%
rename from docs/site/public/no-transform.png
rename to docs/site/src/assets/no-transform.png
diff --git a/docs/site/public/overview_diagram.png b/docs/site/src/assets/overview_diagram.png
similarity index 100%
rename from docs/site/public/overview_diagram.png
rename to docs/site/src/assets/overview_diagram.png
diff --git a/docs/site/public/overview_diagram_dark_mode.png b/docs/site/src/assets/overview_diagram_dark_mode.png
similarity index 100%
rename from docs/site/public/overview_diagram_dark_mode.png
rename to docs/site/src/assets/overview_diagram_dark_mode.png
diff --git a/docs/site/public/pipeline-with-transform.png b/docs/site/src/assets/pipeline-with-transform.png
similarity index 100%
rename from docs/site/public/pipeline-with-transform.png
rename to docs/site/src/assets/pipeline-with-transform.png
diff --git a/docs/site/public/platform_diagram.png b/docs/site/src/assets/platform_diagram.png
similarity index 100%
rename from docs/site/public/platform_diagram.png
rename to docs/site/src/assets/platform_diagram.png
diff --git a/docs/site/public/plugin_overview.png b/docs/site/src/assets/plugin_overview.png
similarity index 100%
rename from docs/site/public/plugin_overview.png
rename to docs/site/src/assets/plugin_overview.png
diff --git a/docs/site/public/plugin_overview.svg b/docs/site/src/assets/plugin_overview.svg
similarity index 100%
rename from docs/site/public/plugin_overview.svg
rename to docs/site/src/assets/plugin_overview.svg
diff --git a/docs/site/public/simple-diagram-asset.png b/docs/site/src/assets/simple-diagram-asset.png
similarity index 100%
rename from docs/site/public/simple-diagram-asset.png
rename to docs/site/src/assets/simple-diagram-asset.png
diff --git a/docs/site/public/simple-flow.png b/docs/site/src/assets/simple-flow.png
similarity index 100%
rename from docs/site/public/simple-flow.png
rename to docs/site/src/assets/simple-flow.png
diff --git a/docs/site/public/tools/storybook/docs-addon.gif b/docs/site/src/assets/tools/storybook/docs-addon.gif
similarity index 100%
rename from docs/site/public/tools/storybook/docs-addon.gif
rename to docs/site/src/assets/tools/storybook/docs-addon.gif
diff --git a/docs/site/public/tools/storybook/events-addon.gif b/docs/site/src/assets/tools/storybook/events-addon.gif
similarity index 100%
rename from docs/site/public/tools/storybook/events-addon.gif
rename to docs/site/src/assets/tools/storybook/events-addon.gif
diff --git a/docs/site/public/tools/storybook/flow-addon.gif b/docs/site/src/assets/tools/storybook/flow-addon.gif
similarity index 100%
rename from docs/site/public/tools/storybook/flow-addon.gif
rename to docs/site/src/assets/tools/storybook/flow-addon.gif
diff --git a/docs/site/public/tools/storybook/flow-reset.gif b/docs/site/src/assets/tools/storybook/flow-reset.gif
similarity index 100%
rename from docs/site/public/tools/storybook/flow-reset.gif
rename to docs/site/src/assets/tools/storybook/flow-reset.gif
diff --git a/docs/site/src/components/ContentTabs.astro b/docs/site/src/components/ContentTabs.astro
new file mode 100644
index 000000000..854010f14
--- /dev/null
+++ b/docs/site/src/components/ContentTabs.astro
@@ -0,0 +1,12 @@
+---
+import { Tabs, TabItem } from "@astrojs/starlight/components";
+---
+
+
+
+
+
+
+
+
+
diff --git a/docs/site/src/components/Image.astro b/docs/site/src/components/Image.astro
new file mode 100644
index 000000000..677866ebf
--- /dev/null
+++ b/docs/site/src/components/Image.astro
@@ -0,0 +1,55 @@
+---
+import { Image as Default, type LocalImageProps } from "astro:assets";
+
+type Props = Omit &
+ (
+ | {
+ src: LocalImageProps["src"];
+ darkModeInvert?: boolean;
+ }
+ | {
+ lightSrc: LocalImageProps["src"];
+ darkSrc: LocalImageProps["src"];
+ }
+ );
+---
+
+
+
+ );
+}
diff --git a/docs/site/src/components/tools/preview/flow-1.json b/docs/site/src/components/tools/preview/flow-1.json
new file mode 100644
index 000000000..5124d4e95
--- /dev/null
+++ b/docs/site/src/components/tools/preview/flow-1.json
@@ -0,0 +1,118 @@
+{
+ "id": "flow-1",
+ "views": [
+ {
+ "id": "view-1",
+ "type": "info",
+ "title": {
+ "asset": {
+ "id": "info-title",
+ "type": "text",
+ "value": "Welcome to Player"
+ }
+ },
+ "primaryInfo": {
+ "asset": {
+ "id": "info-primary",
+ "type": "collection",
+ "values": [
+ {
+ "asset": {
+ "id": "info-primary-1",
+ "type": "text",
+ "value": "This is some content inside of a Player view."
+ }
+ }
+ ]
+ }
+ },
+ "actions": [
+ {
+ "asset": {
+ "id": "action-next",
+ "type": "action",
+ "value": "Next",
+ "label": {
+ "asset": {
+ "id": "action-next-label",
+ "type": "text",
+ "value": "Next"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "id": "view-2",
+ "type": "info",
+ "title": {
+ "asset": {
+ "id": "title",
+ "type": "text",
+ "value": "This is another page in the 1st flow."
+ }
+ },
+ "actions": [
+ {
+ "asset": {
+ "id": "action-back",
+ "type": "action",
+ "value": "Prev",
+ "label": {
+ "asset": {
+ "id": "action-back-label",
+ "type": "text",
+ "value": "Back"
+ }
+ }
+ }
+ },
+ {
+ "asset": {
+ "id": "action-next",
+ "type": "action",
+ "value": "Next",
+ "label": {
+ "asset": {
+ "id": "action-next-label",
+ "type": "text",
+ "value": "Next"
+ }
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "navigation": {
+ "BEGIN": "FLOW_1",
+ "FLOW_1": {
+ "startState": "VIEW_1",
+ "VIEW_1": {
+ "state_type": "VIEW",
+ "ref": "view-1",
+ "transitions": {
+ "Prev": "END_Back",
+ "Next": "VIEW_2"
+ }
+ },
+ "VIEW_2": {
+ "state_type": "VIEW",
+ "ref": "view-2",
+ "transitions": {
+ "Prev": "VIEW_1",
+ "Next": "END_Done"
+ }
+ },
+ "END_Back": {
+ "state_type": "END",
+ "outcome": "back"
+ },
+ "END_Done": {
+ "state_type": "END",
+ "outcome": "done"
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/docs/site/src/components/tools/preview/flow-2.json b/docs/site/src/components/tools/preview/flow-2.json
new file mode 100644
index 000000000..bdd99af0c
--- /dev/null
+++ b/docs/site/src/components/tools/preview/flow-2.json
@@ -0,0 +1,83 @@
+{
+ "id": "flow-2",
+ "views": [
+ {
+ "id": "view-1",
+ "type": "info",
+ "title": {
+ "asset": {
+ "id": "info-title",
+ "type": "text",
+ "value": "This is the 2nd flow."
+ }
+ },
+ "primaryInfo": {
+ "asset": {
+ "id": "info-primary",
+ "type": "collection",
+ "values": [
+ {
+ "asset": {
+ "id": "info-primary-1",
+ "type": "text",
+ "value": "Note the delay between loading flows to emulate a network request/response"
+ }
+ }
+ ]
+ }
+ },
+ "actions": [
+ {
+ "asset": {
+ "id": "action-back",
+ "type": "action",
+ "value": "Prev",
+ "label": {
+ "asset": {
+ "id": "action-back-label",
+ "type": "text",
+ "value": "Back"
+ }
+ }
+ }
+ },
+ {
+ "asset": {
+ "id": "action-next",
+ "type": "action",
+ "value": "Next",
+ "label": {
+ "asset": {
+ "id": "action-next-label",
+ "type": "text",
+ "value": "Continue"
+ }
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "navigation": {
+ "BEGIN": "FLOW_1",
+ "FLOW_1": {
+ "startState": "VIEW_1",
+ "VIEW_1": {
+ "state_type": "VIEW",
+ "ref": "view-1",
+ "transitions": {
+ "Prev": "END_Back",
+ "Next": "END_Done"
+ }
+ },
+ "END_Back": {
+ "state_type": "END",
+ "outcome": "back"
+ },
+ "END_Done": {
+ "state_type": "END",
+ "outcome": "done"
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/docs/site/src/components/tools/preview/flow-3.json b/docs/site/src/components/tools/preview/flow-3.json
new file mode 100644
index 000000000..5d8f96fc3
--- /dev/null
+++ b/docs/site/src/components/tools/preview/flow-3.json
@@ -0,0 +1,68 @@
+{
+ "id": "flow-3",
+ "views": [
+ {
+ "id": "view-1",
+ "type": "info",
+ "title": {
+ "asset": {
+ "id": "info-title",
+ "type": "text",
+ "value": "This is the 3nd and final flow in the series."
+ }
+ },
+ "actions": [
+ {
+ "asset": {
+ "id": "action-back",
+ "type": "action",
+ "value": "Prev",
+ "label": {
+ "asset": {
+ "id": "action-back-label",
+ "type": "text",
+ "value": "Back"
+ }
+ }
+ }
+ },
+ {
+ "asset": {
+ "id": "action-next",
+ "type": "action",
+ "value": "Next",
+ "label": {
+ "asset": {
+ "id": "action-next-label",
+ "type": "text",
+ "value": "Finish"
+ }
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "navigation": {
+ "BEGIN": "FLOW_1",
+ "FLOW_1": {
+ "startState": "VIEW_1",
+ "VIEW_1": {
+ "state_type": "VIEW",
+ "ref": "view-1",
+ "transitions": {
+ "Prev": "END_Back",
+ "Next": "END_Done"
+ }
+ },
+ "END_Back": {
+ "state_type": "END",
+ "outcome": "back"
+ },
+ "END_Done": {
+ "state_type": "END",
+ "outcome": "done"
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/docs/site/components/player-demo/sample-flows/sample-flow-manager.tsx b/docs/site/src/components/tools/preview/sample-flow-manager.tsx
similarity index 98%
rename from docs/site/components/player-demo/sample-flows/sample-flow-manager.tsx
rename to docs/site/src/components/tools/preview/sample-flow-manager.tsx
index ed799b188..11b1cd716 100644
--- a/docs/site/components/player-demo/sample-flows/sample-flow-manager.tsx
+++ b/docs/site/src/components/tools/preview/sample-flow-manager.tsx
@@ -1,4 +1,4 @@
-import {
+import type {
FlowManager,
CompletedState,
Flow,
diff --git a/docs/site/src/content/config.ts b/docs/site/src/content/config.ts
new file mode 100644
index 000000000..a4eec59ba
--- /dev/null
+++ b/docs/site/src/content/config.ts
@@ -0,0 +1,6 @@
+import { defineCollection } from "astro:content";
+import { docsSchema } from "@astrojs/starlight/schema";
+
+export const collections = {
+ docs: defineCollection({ schema: docsSchema() }),
+};
diff --git a/docs/site/pages/assets/cross-platform.mdx b/docs/site/src/content/docs/assets/cross-platform.mdx
similarity index 65%
rename from docs/site/pages/assets/cross-platform.mdx
rename to docs/site/src/content/docs/assets/cross-platform.mdx
index b95fc26c3..ebd54084c 100644
--- a/docs/site/pages/assets/cross-platform.mdx
+++ b/docs/site/src/content/docs/assets/cross-platform.mdx
@@ -1,16 +1,14 @@
---
-title: 'User Player Across Platforms'
+title: Using Player Across Multiple Platforms
---
-# Using Player Across Multiple Platforms
-
One of the major benefits of adopting Player for rendering a UI is it's ability to function across all the platforms Player supports (React, Android, iOS) using the same content. In order to facilitate this, and get the most out of Player's architecture, here's a few things to keep in mind as you integrate Player into multiple platforms.
## Use Core Plugins to Share Functionality
-One of the easiest, and most beneficial thing to do when integrating Player is to organize feature sets into plugins. Keeping each plugin small and concise allows for easy sharing of features with other Player integrations. Player Core, as well as each of the platform integration, supplies an interface for users to augment/extend the functionality of Player. This can be used to author validations, formatters, expressions, etc once, and be shared across Player implementations across platforms. As Player Core runs on every platform, any core Player plugin will also run on every platform which allows for shared functionality to be authored once and shared across every platform.
+One of the easiest, and most beneficial thing to do when integrating Player is to organize feature sets into plugins. Keeping each plugin small and concise allows for easy sharing of features with other Player integrations. Player Core, as well as each of the platform integration, supplies an interface for users to augment/extend the functionality of Player. This can be used to author validations, formatters, expressions, etc once, and be shared across Player implementations across platforms. As Player Core runs on every platform, any core Player plugin will also run on every platform which allows for shared functionality to be authored once and shared across every platform.
-Plugins such as the [common-types plugin](../plugins/common-types) is a great example of a plugin used to add a feature to Player in a reusable way. Since the validations, formats, and data-types present in this plugin are authored in Player Core, we eliminate the need to rewrite them to target each individual platform. Using this mechanism, we also guaranteed that the React, iOS, and Android Player configurations are able to process the same content in the same way across the systems. The most important usecase of this is the asset transforms. Writing the logic to transform the asset as authored in content to the UI representation in the shared transform layer moves repeated functionality to the shared layer decreasing the implementation complexity of each asset on every platform but still leaves room for rendering variability for each platform.
+Plugins such as the [common-types plugin](/plugins/core/common-types) is a great example of a plugin used to add a feature to Player in a reusable way. Since the validations, formats, and data-types present in this plugin are authored in Player Core, we eliminate the need to rewrite them to target each individual platform. Using this mechanism, we also guaranteed that the React, iOS, and Android Player configurations are able to process the same content in the same way across the systems. The most important usecase of this is the asset transforms. Writing the logic to transform the asset as authored in content to the UI representation in the shared transform layer moves repeated functionality to the shared layer decreasing the implementation complexity of each asset on every platform but still leaves room for rendering variability for each platform.
## Use the meta-plugin to simplify plugin sets
@@ -22,6 +20,6 @@ and
> features/expressions/validations added in 1 are automatically present in the other platforms without any additional work.
-*If each plugin implements a single, small feature, how are we able to add new features to each platform without requiring additional work?*
+_If each plugin implements a single, small feature, how are we able to add new features to each platform without requiring additional work?_
-One pattern that we've found to work well is to continue to organize each feature into individual plugins/modules. This allows any application to opt-in to an individual feature, and makes sharing much, much simpler. In addition to this, we also create 1 more plugin using the meta-plugin to wrap all of the application's feature requirements into 1 plugin. This allows additional plugins to to be added to the meta-plugin and each platform will still only require 1 plugin registered (which makes integration easy) while still allowing the individual pieces to be consumed if desired (which makes extensibility easy)
\ No newline at end of file
+One pattern that we've found to work well is to continue to organize each feature into individual plugins/modules. This allows any application to opt-in to an individual feature, and makes sharing much, much simpler. In addition to this, we also create 1 more plugin using the meta-plugin to wrap all of the application's feature requirements into 1 plugin. This allows additional plugins to to be added to the meta-plugin and each platform will still only require 1 plugin registered (which makes integration easy) while still allowing the individual pieces to be consumed if desired (which makes extensibility easy)
diff --git a/docs/site/pages/assets/custom.mdx b/docs/site/src/content/docs/assets/custom.mdx
similarity index 89%
rename from docs/site/pages/assets/custom.mdx
rename to docs/site/src/content/docs/assets/custom.mdx
index 5b9d7b4b3..c91cba540 100644
--- a/docs/site/pages/assets/custom.mdx
+++ b/docs/site/src/content/docs/assets/custom.mdx
@@ -1,13 +1,13 @@
---
-title: 'Custom Assets'
+title: "Custom Assets"
---
-# Custom Assets
+import PlatformTabs from "../../../components/PlatformTabs.astro";
One of the conscious design decisions we made when building Player was to abstract away the actual asset implementation and open it up for users to bring their own when using Player. This way you can seamlessly integrate Player into your existing experiences and reuse UI assets you may have already built. Below we've outlined the way to build custom assets on the various platforms Player supports.
-
+
### Create Your Asset
@@ -16,7 +16,7 @@ First and foremost you need to create a component to handle rendering of your as
```tsx
const CustomAssetComp = (props) => {
return (
-
+
{props.text}
);
@@ -29,9 +29,9 @@ Assuming your authored JSON has a string property named text, this will render t
Now that we have a React component to render our asset, let's create a plugin to register with Player:
-import AssetProviderPlugin from '@player-ui/asset-provider-plugin-react';
-
```javascript
+import AssetProviderPlugin from "@player-ui/asset-provider-plugin-react";
+
class CustomAssetPlugin implements ReactPlayerPlugin{
applyReact(reactPlayer) {
new AssetProviderPlugin([['custom', CustomAssetComp]]).applyReact(reactPlayer);
@@ -48,11 +48,11 @@ Often times, assets contain a reference or slot to another asset. For this to fu
Use the ReactAsset Component from the `@player-ui/react` package with the nested asset as props to dynamically determine the rendering implementation to use:
```jsx
-import { ReactAsset } from '@player-ui/react';
+import { ReactAsset } from "@player-ui/react";
const CustomAssetComp = (props) => {
return (
-
+
{props.header && }
{props.text}
@@ -62,14 +62,14 @@ const CustomAssetComp = (props) => {
This would automatically find the appropriate handler for the `props.header` asset and use that to render.
-
-
+
+
SwiftUI Player assets are made of 3 parts:
-- [Data](/#Data): Decodable AssetData
-- [View](/#View): A SwiftUI View
-- [Asset](/#Asset): SwiftUIAsset implementation to tie the two together
+- [Data](#data): Decodable AssetData
+- [View](#view): A SwiftUI View
+- [Asset](#asset): SwiftUIAsset implementation to tie the two together
[Registering Your Asset](#registering-your-asset): Additional Topic
@@ -217,21 +217,20 @@ struct SomeView: View {
If your experience will be used on multiple platforms, it is not advised to use this method, a transform will ensure the same logic is followed on all 3 platforms and is strongly encouraged.
-
-
+
+
In order to render an asset a renderer for that type must be registered in the Android Player. If a renderer is found, then Player will delegate rendering when that type is encountered, otherwise Player will skip that node. Creating and registering such a renderer requires the following:
1. [Extending DecodableAsset](#extending-decodableasset)
- 1. [Implementing `initView` and `hydrate`](#implementing-initview)
- 2. [Define data structure](#accessing-data)
- 3. [Nested assets](#nested-assets)
- 4. [Styling](#styling)
+ 1. [Implementing `initView` and `hydrate`](#implementing-initview)
+ 2. [Define data structure](#accessing-data)
+ 3. [Nested assets](#nested-assets)
+ 4. [Styling](#styling)
2. [Registering assets](#registering-your-asset)
### Extending DecodableAsset
-
`DecodableAsset` is a subclass of `RenderableAsset` that contains data decoding capabilities built on [Kotlinx Serialization](https://github.com/Kotlin/kotlinx.serialization). This is the recommended approach for creating an asset and will be consolidated with `RenderableAsset` in future versions of the Android Player. On top of the requirements for subclassing `RenderableAsset`, subclassing `DecodableAsset` requires passing a `KSerializer` for the data class that represents the data for that asset.
`RenderableAsset` is the base structure used by Player to convert parsed content into Android Views. Each implementation is instantiated with an `AssetContext` and is required to implement two methods, `initView` and `hydrate`. The separation of logic between these two methods allow for views to be cached and optimize the render process. However, both of these methods are only used internally via the `render` method. `render` is the main entry point for getting the Android view representation of that asset. It automatically handles the caching and hydration optimizations, only rebuilding and rehydrating when a dependency has changed. The caller would be responsible for handling that view (i.e. injecting it into a ViewGroup).
@@ -293,16 +292,18 @@ val stringToRender: String = asset.getString("value")
```json
// ...
{
- "id": "some-card",
- "type": "card",
- "title": {
- "asset": {
- "id": "some-text",
- "type": "text",
- "value": "This is a text asset"
- }
+ "id": "some-card",
+ "type": "card",
+ "title": {
+ "asset": {
+ "id": "some-text",
+ "type": "text",
+ "value": "This is a text asset"
}
+ }
}
+
+
// ...
```
@@ -351,16 +352,15 @@ fun View.hydrate() {
}
```
-
+
-
### Registering your Asset
When registering your asset with an `AssetRegistry`, it can either be registered as a new type, if it is an entirely new construct, or registered as a variant of an existing asset type, to only be rendered under certain conditions.
-
+
```tsx
// Using AssetProviderPlugin from '@player-ui/asset-provider-plugin-react'
@@ -370,21 +370,21 @@ new AssetProviderPlugin([
//This will register a match on { type: 'example', metaData: {"role": "someRole"} }
[{ type: 'example', metaData: {"role": "someRole"}}, ExampleAsset])
```
-
-
+
+
```swift
// Convenience function for just registering for type
player.assetRegistry.register("example", asset: ExampleAsset.self)
-// Registers the type with the metaData present with someRole
+// Registers the type with the metaData present with someRole
player.assetRegistry.register(["type": "example", "metaData": ["role": "someRole"]], for: ExampleAsset.self)
```
-
-
+
+
Registering assets is done in the `AndroidPlayerPlugin`. Each plugin only needs to implement an `apply` method which gives the plugin the opportunity to supplement core player functionality. The `AndroidPlayer` instance contains an asset registry where assets should be register. A helper method has been created to make registration as simple as providing the type and a factory. The factory method must take an AssetContext, and is recommended to just be the constructor of your asset.
@@ -397,7 +397,7 @@ val map = mapOf("type" to "example", "metaData" to mapOf("role" to "someRole"))
androidPlayer.assetRegistry.set(map, ::ExampleAsset)
```
-
+
In the latter case, it is recommended to extend the original asset, so as to avoid boilerplate for data and construction, and just override the render function. If your variant will have additional data decoded that the original asset does not have, you will need to create the whole asset.
@@ -411,27 +411,26 @@ In the latter case, it is recommended to extend the original asset, so as to avo
For more info on transform registration see [Asset Transform Plugin](https://player-ui.github.io/latest/plugins/asset-transform#asset-transform-plugin)
### Use Cases
+
Below are 3 different use cases for different ways to mix and match the asset and transform registry to simplify the asset implementation
#### Use Case 1: Same type with different variants and asset implementations that can share the same transform
-
-
-
+
- ```tsx
+```tsx
// Using AssetProviderPlugin from '@player-ui/asset-provider-plugin-react'
new AssetProviderPlugin([
- //This will register a match on { type: 'example' }
- ['example', ExampleAsset],
- //This will register a match on { type: 'example', metaData: {"role": "someRole"} }
- [{ type: 'example', metaData: {"role": "someRole"}}, ExampleAsset]
- ])
+ //This will register a match on { type: 'example' }
+ ["example", ExampleAsset],
+ //This will register a match on { type: 'example', metaData: {"role": "someRole"} }
+ [{ type: "example", metaData: { role: "someRole" } }, ExampleAsset],
+]);
```
-
-
+
+
```swift
player.assetRegistry.register("input", asset: InputAsset.self)
@@ -439,44 +438,43 @@ player.assetRegistry.register("input", asset: InputAsset.self)
player.assetRegistry.register(["type": "input", "dataType": ["type": "DateType"]], for: DateInputAsset.self)
```
-
-
+
+
- ```kotlin
+```kotlin
androidPlayer.registerAsset("input", ::InputAsset)
val map = mapOf("type" to "input", "dataType" to mapOf("type" to "DateType"))
androidPlayer.assetRegistry.set(map, ::DateInputAsset)
```
-
-
+
If the common InputData fields for the decoded data looks like:
-
+
Taken from the reference asset Input Asset example, see [full transform implementation](https://github.com/player-ui/player/blob/main/plugins/reference-assets/core/src/assets/input/transform.ts)
+
```tsx
export interface InputAsset {
- id: String
- type: String
- value: String?
+ id: String;
+ type: String;
+ value: String?;
}
export interface TransformedInput extends InputAsset {
/** A function to commit the new value to the data-model */
- set: (newValue: ValueType) => void;
+ set: (newValue: ValueType) => void;
/** The `DataType` associated with this asset, for formatting the keyboard */
dataType?: DataType;
}
```
-
-
-
+
+
The InputData used in Swift and Android is using the TransformedInput which includes the original web input properties plus additional transform specific properties
@@ -492,8 +490,8 @@ struct InputData: AssetData {
}
```
-
-
+
+
The InputData used in Swift and Android is using the TransformedInput which includes the original web input properties plus additional transform specific properties
@@ -508,18 +506,15 @@ data class InputData(
)
```
-
+
And we would like to render two different assets based on whether or not "dataType" is present then both InputAsset and DateInputAsset can share the same InputData which can contain a transform (such as the function to perform after input data is set) but show different content for the views such as input accessories like a calender based on the DataType
-
#### Use Case 2: Same type with different variants and asset implementations that don't share the same transform
-
-
-
+
```tsx
// Using AssetProviderPlugin from '@player-ui/asset-provider-plugin-react'
@@ -529,9 +524,8 @@ new AssetProviderPlugin([
])
```
-
-
-
+
+
```swift
player.assetRegistry.register("input", asset: InputAsset.self)
@@ -539,8 +533,8 @@ player.assetRegistry.register("input", asset: InputAsset.self)
player.assetRegistry.register(["type": "input", "dataType": ["type": "DateType"]], for: DateInputAsset.self)
```
-
-
+
+
```kotlin
androidPlayer.registerAsset("input", ::InputAsset)
@@ -549,37 +543,37 @@ val map = mapOf("type" to "input", "dataType" to mapOf("type" to "DateType"))
androidPlayer.assetRegistry.set(map, ::DateInputAsset)
```
-
+
If the common InputData fields for the decoded data looks like:
-
+
```tsx
export interface InputAsset {
- id: String
- type: String
- value: String?
+ id: String;
+ type: String;
+ value: String?;
}
export interface DateInputAsset {
- id: String
- type: String
- value: String?
+ id: String;
+ type: String;
+ value: String?;
}
// Used in the transform function for inputTranform
export interface TransformedInput extends InputAsset {
/** A function to commit the new value to the data-model */
- set: (newValue: ValueType) => void;
+ set: (newValue: ValueType) => void;
}
// Used in the transform function for inputDateTranform
export interface TransformedDateInput extends DateInputAsset {
- /** A function to commit the new value to the data-model */
- set: (newValue: ValueType) => void;
+ /** A function to commit the new value to the data-model */
+ set: (newValue: ValueType) => void;
/** The `DataType` associated with this asset, for formatting the keyboard */
dataType?: DataType;
}
@@ -588,8 +582,8 @@ export interface TransformedDateInput extends DateInputAsset {
In the case where the regular InputAsset and the DateInputAsset should not share the same transform, its possible to target the variant in the transform registration (since transform also use the partial match registry) to specify a different transform when the "dataType" is present for example:
```tsx
-import { Player } from '@player-ui/player';
-import { AssetTransformPlugin } from '@player-ui/asset-transform-plugin';
+import { Player } from "@player-ui/player";
+import { AssetTransformPlugin } from "@player-ui/asset-transform-plugin";
// Add it to Player
@@ -598,17 +592,17 @@ const player = new Player({
new AssetTransformPlugin(
new Registry([
// Register a match for any input type with a custom transform.
- [{ type: 'input' }, inputTransform],
+ [{ type: "input" }, inputTransform],
// Register a match for any input type that has dataType DateType with a custom transform.
- [{ type: 'input', "dataType": {type: "DateType"} }, dateInputTransform]
- ])
- )
- ]
-});
+ [{ type: "input", dataType: { type: "DateType" } }, dateInputTransform],
+ ]),
+ ),
+ ],
+});
```
-
-
+
+
The InputData used in Swift and Android is using the TransformedInput which includes the original web input properties plus additional transform specific properties
@@ -624,8 +618,8 @@ struct InputData: AssetData {
}
```
-
-
+
+
The InputData used in Swift and Android is using the TransformedInput which includes the original web input properties plus additional transform specific properties
@@ -640,29 +634,24 @@ data class InputData(
)
```
-
+
-
-
#### Use Case 3: Different type, same asset implementation, different transforms
-
-
-
+
- ```tsx
+```tsx
// Using AssetProviderPlugin from '@player-ui/asset-provider-plugin-react'
new AssetProviderPlugin([
- ['choiceA', Choice],
- ['choiceB', Choice]
-])
+ ["choiceA", Choice],
+ ["choiceB", Choice],
+]);
```
-
-
-
+
+
```swift
player.assetRegistry.register("choiceA", asset: ChoiceAsset.self)
@@ -670,8 +659,8 @@ player.assetRegistry.register("choiceA", asset: ChoiceAsset.self)
player.assetRegistry.register("choiceB", asset: ChoiceAsset.self)
```
-
-
+
+
```kotlin
androidPlayer.registerAsset("choiceA", ::ChoiceAsset)
@@ -679,7 +668,7 @@ androidPlayer.registerAsset("choiceA", ::ChoiceAsset)
androidPlayer.registerAsset("choiceB", ::ChoiceAsset)
```
-
+
Its possible to register the same asset implementation to different type names with the same variant, this may be needed if the two types visually look the same but behaviourally is different such as when the choice is clicked "choiceA" does one action but "choiceB" does something else which is defined in the transform
@@ -687,7 +676,7 @@ Its possible to register the same asset implementation to different type names w
Since the transform is called on "select" of the `WrappedFunction` or `Invokable` in the data this doesnt change the ChoiceData (only the values of select function itself change depending on if we get ChoiceA or ChoiceB) which means they can both be registered to ChoiceAsset
-
+
```jsx
export interface Choice {
@@ -706,8 +695,8 @@ Create two transforms choiceATransform and choiceBTransform that both return Tra
Then in the web transform registration choiceA and choiceB are registered to those different transforms
```jsx
-import { Player } from '@player-ui/player';
-import { AssetTransformPlugin } from '@player-ui/asset-transform-plugin';
+import { Player } from "@player-ui/player";
+import { AssetTransformPlugin } from "@player-ui/asset-transform-plugin";
// Add it to Player
@@ -716,19 +705,20 @@ const player = new Player({
new AssetTransformPlugin(
new Registry([
// Register a match for any choiceA type with a custom transform.
- [{ type: 'choiceA' }, choiceATransform],
+ [{ type: "choiceA" }, choiceATransform],
// Register a match for any choiceB type with a custom transform.
- [{ type: 'choiceB' }, choiceBTransform]
- ])
- )
- ]
-});
+ [{ type: "choiceB" }, choiceBTransform],
+ ]),
+ ),
+ ],
+});
```
-
-
+
+
The ChoiceData used in Swift and Android is using the TransformedChoice which includes the original web choice properties plus additional transform specific properties
+
```swift
struct ChoiceData: AssetData {
var id: String
@@ -739,10 +729,11 @@ struct ChoiceData: AssetData {
}
```
-
-
+
+
The ChoiceData used in Swift and Android is using the TransformedChoice which includes the original web choice properties plus additional transform specific properties
+
```kotlin
@Serializable
data class ChoiceData(
@@ -754,9 +745,7 @@ data class ChoiceData(
)
```
-
+
-
-
Overall the asset and transform registry gives developers a lot of flexibility for extending and simplifying assets based on given constraints
diff --git a/docs/site/pages/assets/dsl.mdx b/docs/site/src/content/docs/assets/dsl.mdx
similarity index 80%
rename from docs/site/pages/assets/dsl.mdx
rename to docs/site/src/content/docs/assets/dsl.mdx
index d83da32ca..7b890770f 100644
--- a/docs/site/pages/assets/dsl.mdx
+++ b/docs/site/src/content/docs/assets/dsl.mdx
@@ -2,24 +2,22 @@
title: Writing DSL Components
---
-# Creating TSX Components
-
In order to take advantage of the auto-completion and validation of TypeScript types, asset libraries can export a component library for content authoring. Creating components isn't much different than writing a React component for the web. The primative elements uses the [react-json-reconciler](https://github.com/intuit/react-json-reconciler) to create the JSON content tree, with utilities to make it quick and painless to create new asset-components.
-
## Creating a Basic Component
The `Asset` component from the `@player-tools/dsl` package is the quickest way to create a new component. The `Asset` component will take all the Asset's properties and convert them to their equivalent JSON representation when serialized.
-In the examples below, we'll be creating a TSX component for the `action` asset in our reference set.
+In the examples below, we'll be creating a TSX component for the `action` asset in our reference set.
The `action` asset has a `label` slot (which is typically used as a `text` asset), a `value` (for flow transitions), and an `exp` for evaluating expressions.
For this example we'll use a resemblance of this type, but in practice types should be imported directly from their asset rather than duplicating them.
```ts
-import type { Asset, AssetWrapper, Expression } from '@player-ui/player';
+import type { Asset, AssetWrapper, Expression } from "@player-ui/player";
-export interface ActionAsset extends Asset<'action'> {
+export interface ActionAsset
+ extends Asset<"action"> {
/** The transition value of the action in the state machine */
value?: string;
@@ -36,26 +34,26 @@ _Note: The `Asset` type we're importing here from the `@player-ui/player` packag
To turn this interface into a usable component, create a new React component that _renders_ an Asset:
```tsx
-import { Asset, AssetPropsWithChildren } from '@player-tools/dsl';
+import { Asset, AssetPropsWithChildren } from "@player-tools/dsl";
export const Action = (props: AssetPropsWithChildren) => {
return ;
-}
+};
```
This would allow users to import the `Action` component, and _render_ it to JSON:
```tsx
-const myView =
+const myView = ;
```
-which when compiled would look like
+which when compiled would look like
```json
{
- "id": "root",
- "type": "action",
- "value": "next"
+ "id": "root",
+ "type": "action",
+ "value": "next"
}
```
@@ -63,8 +61,7 @@ The `AssetPropsWithChildren` type is a utility type to help convert the `Asset`
## Slots
-Continuing the example fo the `ActionAsset`, we need a way for users to users to specify the nested `label` property, which itself is another asset. This can be accomplished using the `createSlot` utility function. The `createSlot` function also accept components to enable automatically creating `text` and `collection` assets when they aren't specified where needed. If these components aren't passed into the slot when used, the resulting content may be invalid. Let's add a `Label` slot to our `Action` component to allow it to be easily authored. Lets assume we already have a `Text` and `Collection` component.
-
+Continuing the example fo the `ActionAsset`, we need a way for users to users to specify the nested `label` property, which itself is another asset. This can be accomplished using the `createSlot` utility function. The `createSlot` function also accept components to enable automatically creating `text` and `collection` assets when they aren't specified where needed. If these components aren't passed into the slot when used, the resulting content may be invalid. Let's add a `Label` slot to our `Action` component to allow it to be easily authored. Lets assume we already have a `Text` and `Collection` component.
```tsx
import React from 'react';
@@ -94,9 +91,10 @@ const myView = (
);
```
+which can also be written as the following because the slot has a `TextComp` passed in for it which allows the automatic creation of a text asset for any regular text that is passed in the slot
```tsx
-import React from 'react';
+import React from "react";
const myView = (
@@ -105,20 +103,20 @@ const myView = (
);
```
-which when compiled would look like (note the auto injection of the `Text` asset and corresponding Asset Wrapper):
+When compiled, both examples would look like (note the auto injection of the `Text` asset and corresponding Asset Wrapper):
```json
{
- "id": "root",
- "type": "action",
- "value": "next",
- "label": {
- "asset": {
- "id": "root-label-text",
- "type": "text",
- "value": "Continue"
- }
+ "id": "root",
+ "type": "action",
+ "value": "next",
+ "label": {
+ "asset": {
+ "id": "root-label-text",
+ "type": "text",
+ "value": "Continue"
}
+ }
}
```
@@ -128,8 +126,8 @@ And if we wanted to have the `label` property to have to text assets we could wr
const myView = (
- Some
- Text
+ Some
+ Text
);
@@ -139,30 +137,31 @@ which when compiled would look like the following (note the automatic insertion
```json
{
- "id": "root",
- "type": "action",
- "value": "next",
- "label": {
- "asset": {
- "id": "root-collection",
+ "id": "root",
+ "type": "action",
+ "value": "next",
+ "label": {
+ "asset": {
+ "id": "root-collection",
+ "type": "text",
+ "values": [
+ {
+ "asset": {
+ "id": "root-collection-1-text",
+ "type": "text",
+ "value": "Some"
+ }
+ },
+ {
+ "asset": {
+ "id": "root-collection-2-text",
"type": "text",
- "values": [
- {
- "asset": {
- "id": "root-collection-1-text",
- "type": "text",
- "value": "Some"
- }
- },{
- "asset": {
- "id": "root-collection-2-text",
- "type": "text",
- "value": "Text"
- }
- }
- ]
+ "value": "Text"
+ }
}
+ ]
}
+ }
}
```
@@ -170,18 +169,18 @@ which when compiled would look like the following (note the automatic insertion
While a majority of Assets can be described simply via the base `Action` Component, there are certain cases where DSL components need to contain a bit more logic. This section aims to describe further tools that are offered in the `@player-tools/dsl` package.
-### Components with Specially Handled Properties
+### Components with Specially Handled Properties
-In the previous example, we covered how to create a DSL Component for our reference `Action` Asset. Our actual Action Asset however looks a little bit different.
+In the previous example, we covered how to create a DSL Component for our reference `Action` Asset. Our actual Action Asset however looks a little bit different.
```tsx
-import React from 'react';
+import React from "react";
export const Action = (
- props: Omit, 'exp'> & {
+ props: Omit, "exp"> & {
/** An optional expression to execute before transitioning */
exp?: ExpressionTemplateInstance;
- }
+ },
) => {
const { exp, children, ...rest } = props;
@@ -196,12 +195,10 @@ export const Action = (
Crucially, the difference is in how the `exp` property is handled. As the `exp` property is an `Expression`, if we just allowed the `Action` component to process this property, we would end up with an `ExpressionTemplate` instance _not_ an `Expression` instance. While technically they are equivalent, there is no need to wrap the final string in the Expression Template tags (`@[]@`) since we know the string will be an `Expression` and it will just lead to additonal procssing at runtime. Therefore, we need to do a few things to properly construct this DSL component.
-The first is to modify the type for the commponent. In the above code snippit we are using the `Omit` type to remove the base `exp` property from the source type and replacing it with an `exp` property that expects a `ExpressionTemplateInstance` which allows an DSL expression to be passed in.
+The first is to modify the type for the commponent. In the above code snippit we are using the `Omit` type to remove the base `exp` property from the source type and replacing it with an `exp` property that expects a `ExpressionTemplateInstance` which allows an DSL expression to be passed in.
The second is to extract out the `exp` property from the props and use a `property` component to manually control how that property will get serialized. This component is exposed by the underlying `react-json-reconciler` library which also supplies an `array`, `obj` and `value` component to allow full control over more complicated data structures. The `@player-tools/dsl` package also exposes the `toJsonProperties` function to process whole non-Asset objects.
### View Components
For Assets that are intended to be Views, a `View` component is exported from the `@player-tools/dsl` package. Its usage is exactly the same as the `Asset` component, however it correctly handles the serialization of any Crossfield Validations that exist on the View.
-
-
diff --git a/docs/site/pages/assets/index.mdx b/docs/site/src/content/docs/assets/index.mdx
similarity index 72%
rename from docs/site/pages/assets/index.mdx
rename to docs/site/src/content/docs/assets/index.mdx
index cf3f9fe5b..af837b02b 100644
--- a/docs/site/pages/assets/index.mdx
+++ b/docs/site/src/content/docs/assets/index.mdx
@@ -1,8 +1,9 @@
---
-title: 'Assets'
+title: "Assets"
---
-# Assets
+import Image from "../../../components/Image.astro";
+import assetPartsImage from "../../../assets/asset-parts.png";
An asset is a generic term given to a semantic bit of information that we wish to convey to the user. Assets are the backbone that make up the content that Player renders. Though there are many different types of assets, they all follow the same basic principles:
@@ -19,7 +20,7 @@ There are a few key components that make up an asset:
- How it interacts with Player
- How it should render
-![Asset Parts](/asset-parts.png?darkModeInvert)
+
With few exceptions, an asset requires all three of these to be defined to fully function.
@@ -29,12 +30,12 @@ The schema of an asset describes the contract between the input content (what us
#### Data Interaction
-The next logical step is the contract between Player (it's data-model, validation rules, etc.) and an instance of an asset in a view. These are described through transform functions, which are stateless mapping functions orchestrated during the view reconciliation processing. You can read more about asset transforms [here](./assets/transforms)
+The next logical step is the contract between Player (it's data-model, validation rules, etc.) and an instance of an asset in a view. These are described through transform functions, which are stateless mapping functions orchestrated during the view reconciliation processing. You can read more about asset transforms [here](./transforms)
#### UI Rendering
The last step of the puzzle is how the asset is physically displayed to a user. Given the output of the transform, it presents the user with data to display, or an interactive element to capture a response. Unlike the first 2 parts, the rendering is platform dependent and requires an implementation for each platform you're using Player with.
-# Asset Bundles
+## Asset Bundles
-In many cases, sets of assets are bundled together and loaded via a single [plugin](../plugins/asset-provider). For the three platforms we support (iOS, Android, and React), a reference set is created as an example. These provide a variety of common types of assets users may end up creating. While they _are_ capable of being used in a production application, they shouldn't be viewed as a standard set -- but merely an example for teams and apps to create their own standard set. To read more about the reference assets check out the [reference](./assets/reference) section.
\ No newline at end of file
+In many cases, sets of assets are bundled together and loaded via a single [plugin](../plugins/multiplatform/asset-provider). For the three platforms we support (iOS, Android, and React), a reference set is created as an example. These provide a variety of common types of assets users may end up creating. While they _are_ capable of being used in a production application, they shouldn't be viewed as a standard set -- but merely an example for teams and apps to create their own standard set. To read more about the reference assets check out the [reference](./reference) section.
diff --git a/docs/site/pages/assets/reference.mdx b/docs/site/src/content/docs/assets/reference.mdx
similarity index 87%
rename from docs/site/pages/assets/reference.mdx
rename to docs/site/src/content/docs/assets/reference.mdx
index a396f0559..c94b66e42 100644
--- a/docs/site/pages/assets/reference.mdx
+++ b/docs/site/src/content/docs/assets/reference.mdx
@@ -1,19 +1,20 @@
---
-title: 'Reference Assets'
+title: "Reference Assets"
---
-# Reference Assets
+import PlatformTabs from "../../../components/PlatformTabs.astro";
+
To help users get started with Player, we have created a minimal set of useable assets for React, iOS and Android. These reference assets showcase the design philosophy we encourage when building your own asset sets. While these components are functional we _do not_ recommend shipping them to production as they have not been tested to be production ready.
-
+
For the React Player, we ship a package (`@player-ui/reference-assets-plugin-react`) that provides the reference set of assets. Each asset package exposes a `Component`, type, and optional transform. They also export hooks for easily consuming the transformed component and supplying your own UI for a custom look and feel. These components are all then exposed via a plugin that can be added to Player like so:
```javascript
-import { ReactPlayer } from '@player-ui/react';
-import { ReferenceAssetsPlugin } from '@player-ui/reference-assets-plugin-react';
+import { ReactPlayer } from "@player-ui/react";
+import { ReferenceAssetsPlugin } from "@player-ui/reference-assets-plugin-react";
const reactPlayer = new ReactPlayer({
plugins: [new ReferenceAssetsPlugin()],
@@ -24,8 +25,8 @@ const reactPlayer = new ReactPlayer({
The reference assets + React player can be viewed in [Storybook](/storybook-demo)
-
-
+
+
Alongside distributing the `PlayerUI` pod, there is a `PlayerUI/ReferenceAssets` subspec used as examples of how Player APIs work for building assets. This pod uses the shared TypeScript transform functions that the React and Android players use for their reference assets, ensuring consistent behavior across platforms. These assets can be loaded into Player like so:
@@ -45,8 +46,8 @@ struct MyApp: View {
}
```
-
-
+
+
Alongside distributing the Android Player framework, there is a reference assets library used as an example of how Player APIs work for building assets. These are intended to serve as a reference, but can be used early on in development as a means of understanding how to work with Player. This asset set uses the shared TypeScript transform functions that the Web and Android players use for their reference assets, ensuring consistent behavior across platforms. These assets can be loaded into Player like so:
@@ -55,6 +56,6 @@ import com.intuit.playerui.android.reference.assets.ReferenceAssetsPlugin
val player = AndroidPlayer(context, ReferenceAssetsPlugin())
```
-
-
+
+
diff --git a/docs/site/src/content/docs/assets/transforms.mdx b/docs/site/src/content/docs/assets/transforms.mdx
new file mode 100644
index 000000000..1a0c926a2
--- /dev/null
+++ b/docs/site/src/content/docs/assets/transforms.mdx
@@ -0,0 +1,44 @@
+---
+title: "Transforms"
+---
+
+import Image from "../../../components/Image.astro";
+import assetPipelineImage from "../../../assets/simple-diagram-asset.png";
+import assetWithoutTransformImage from "../../../assets/no-transform.png";
+import assetWithTransformImage from "../../../assets/pipeline-with-transform.png";
+
+This guide will walk through a few of the core concepts of assets, transforms and how they come together with the UI to create an experience.
+
+You can read more about what an asset is [here](/content/assets-views). In short:
+
+> An asset is a generic term given to a semantic bit of information that we wish to convey to the user. Assets are the primitive elements that make up the content that players present as user experiences.
+
+For all intents and purposes, views are equivalent to assets for this guide.
+
+## Assets and the UI
+
+In general, the pipeline for user-content is something like:
+
+
+
+Player will do minimal processing of each asset in the tree, resolving [data in strings](/content/data-and-expressions), [applicability](/content/assets-views#applicability) and any other generic processing it can. The processed tree is then sent to the rendering layer, where it is turned into a native component on the system Player is running on.
+
+For simple Assets, like text, there's no need for any asset specific processing. The output of Player is enough to successfully render and display the content to the user.
+
+
+
+## Transforms
+
+When dealing with user interactions(`inputs`, `selections`) or some further data/communication is needed with Player, we expose a mechanism for individual assets to augment Player's processing with it's own custom data. By breaking this out into it's own discrete step (outside of the UI), we allow asset state to exist outside on an individual rendering, and thus sharable across platforms. These augmentations are processed through a stateless function called a transform.
+
+
+
+Transforms can be added through the [asset-transform](/plugins/core/asset-transform) plugin, and they run as part of the core player's reconciliation step. This improves performance, as the transforms are cached between updates to the view, and re-usable as they can be registered across platforms to share common logic for assets. You can refer to the [cross-platform](../cross-platform) guide on sharing Player logic across multiple platforms.
diff --git a/docs/site/pages/content/assets-views.mdx b/docs/site/src/content/docs/content/assets-views.mdx
similarity index 82%
rename from docs/site/pages/content/assets-views.mdx
rename to docs/site/src/content/docs/content/assets-views.mdx
index 364ed2743..4dbf131b1 100644
--- a/docs/site/pages/content/assets-views.mdx
+++ b/docs/site/src/content/docs/content/assets-views.mdx
@@ -1,8 +1,10 @@
---
-title: 'Assets & Views'
+title: "Assets & Views"
---
-# Assets
+import ContentTabs from "../../../components/ContentTabs.astro";
+
+## Assets
An asset is a generic term given to a semantic bit of information that we wish to convey to the user. Assets are the primitive elements that make up the content Player presents as user experiences. Though there are many different types of assets, they all follow the same basic principles:
@@ -18,6 +20,20 @@ Each asset must have 2 properties: an `id` and `type`:
Nested assets are represented as objects containing an `asset` property. For example:
+
+
+```tsx
+import { Asset } from '@player-tools/dsl';
+
+
+
+
+
+
+```
+
+
+
```json
{
"id": "parent",
@@ -30,21 +46,43 @@ Nested assets are represented as objects containing an `asset` property. For exa
}
}
```
+
+
The `label` of the parent contains a nested asset reference. These are _slots_ that can usually contain any asset type.
-# Views
+## Views
Views are _assets_ that exist at the top level of the tree. They typically include the navigation actions, a title, or other top-level information.
The `id` of the views are used in the navigation section to reference a specific view from the list.
-## Cross-field validation
+### Cross-field validation
-The other special property of a `view` vs. an `asset` is the addition of a `validation` property on the view. These contain [`validation` objects](/schema) that are used for validations crossing multiple fields, and are ran on user navigation rather than data change.
+The other special property of a `view` vs. an `asset` is the addition of a `validation` property on the view. These contain [`validation` objects](../schema#validation) that are used for validations crossing multiple fields, and are ran on user navigation rather than data change.
Example:
+
+
+```tsx
+import { View, expression as e, binding as b } from '@player-tools/dsl';
+
+
+```
+
+
+
```json
{
...
@@ -63,6 +101,8 @@ Example:
]
}
```
+
+
They follow the same guidelines for normal validation references, with the addition of a `ref` property that points to the binding that this validation is tied to.
@@ -70,20 +110,20 @@ They follow the same guidelines for normal validation references, with the addit
Any object in the tree (including _assets_) may contain an `applicability` property. This is an _expression_ that may conditionally show or hide an asset (and all of it's children) from the view tree. Applicability is dynamically calculated and will automatically update as data changes on the page.
-# Switches
+## Switches
-Switches are ways of dynamically changing the structure of the view based on data. There are 2 types of switches: `static` and `dynamic`, but their structures are identical. `switches` can appear anywhere you'd find a normal asset, and (similar to [templates](./templates)) are removed from the view before it reaches the UI layer.
+Switches are ways of dynamically changing the structure of the view based on data. There are 2 types of switches: `static` and `dynamic`, but their structures are identical. `switches` can appear anywhere you'd find a normal asset, and (similar to [templates](./#templates)) are removed from the view before it reaches the UI layer.
-## Usage
+### Usage
The switch is simply a list of objects with `case` and `asset` properties:
- `asset` - The asset that will replace the switch if the case is true
-- `case` - An [expression](./expression) to evaluate.
+- `case` - An [expression](../data-expressions#expressions) to evaluate.
The switch will run through each _case_ statement until the first case expression evaluates to true. For the _default_ case, simple use a value of `true` at the end of the array.
-## Static v Dynamic Switches
+### Static v Dynamic Switches
The only difference between a `static` and `dynamic` switch is the timing update behavior after the first rendering of a view.
@@ -91,15 +131,37 @@ A `staticSwitch` calculates the applicable case when a view first renders. It wi
A `dynamicSwitch` will always update the applicable case statement whenever data changes. If data is changed while a view is still showing, the switch will be updated to reflect the new case.
-## Example
+### Example
Anywhere you can place an `asset` node, a `dynamicSwitch` or `staticSwitch` can be placed instead.
+
+
+```tsx
+import { Switch, Asset, expression as e, binding as b } from '@player-tools/dsl';
+
+
+
+
+
+
+
+
+
+
+
+
+
+````
+
+
+
+
```json
{
"staticSwitch": [
{
- "case": "{{name.first}} == 'adam'",
+ "case": "{{name.first}} == 'John'",
"asset": {
"id": "name",
"type": "text",
@@ -107,7 +169,7 @@ Anywhere you can place an `asset` node, a `dynamicSwitch` or `staticSwitch` can
}
},
{
- "case": "{{name.first}} == 'notadam'",
+ "case": "{{name.first}} == 'Jane'",
"asset": {
"id": "name",
"type": "text",
@@ -124,13 +186,16 @@ Anywhere you can place an `asset` node, a `dynamicSwitch` or `staticSwitch` can
}
]
}
-```
+````
-# Templates
+
+
+
+## Templates
Templates provide a way to dynamically create a list of assets, or _any_ object, based on data from the model. All of the templating semantics are removed by the time it reaches an asset's transform or UI layer.
-## Usage
+### Usage
Within any asset, specify a `template` property as an array of:
@@ -141,7 +206,7 @@ Within any asset, specify a `template` property as an array of:
Within a template, the `_index_` string can be used to substitute the array-index of the item being mapped.
-### Example
+#### Example
**Authored**
@@ -194,17 +259,17 @@ Within a template, the `_index_` string can be used to substitute the array-inde
}
```
-## Multiple templates
+### Multiple templates
There's a few ways to leverage multiple templates within a single asset. Templates can be _nested_ or multiple used on a single node. These can also be combined to build out complicated nested expansion.
-### Nested Templates
+#### Nested Templates
Templates can contain other templates. When referencing a nested template, append the template depth to the `_index_` string to reference the correct data-item.
For example, if 1 template contains another, use `_index_` to reference the outer-loop, and `_index1_` to reference the inner loop. Furthermore, if templates are nested three levels deep, the first level loop will still be referenced by `_index_`, the second level will be referenced by `_index1_` and the bottom most loop will be referenced by `_index2_`.
-### Multiple Templates - Single Output
+#### Multiple Templates - Single Output
Templates will, by default, create an array, if needed, for the `output` property of each template. If that array already exits (either by manually writing it in the JSON, or from a previous template run), each item will be appended to the end of the existing array.
@@ -282,7 +347,7 @@ The template below will append it's values to the pre-existing `values` array.
}
```
-## Dynamic and Static Templates
+### Dynamic and Static Templates
Like switches, the only difference between a `static` and `dynamic` template is the timing update behavior after the first rendering of a view. If not defined, the value of `dynamic` is default to `false`.
@@ -316,8 +381,8 @@ If `dynamic` is `true`, template will be always updated whenever data changes. I
```
```typescript
-model.set([['list.of.names', ['Jain']]]);
-model.set([['list.of.names', ['Jain', 'Erica']]]);
+model.set([["list.of.names", ["Jain"]]]);
+model.set([["list.of.names", ["Jain", "Erica"]]]);
```
**Output**
diff --git a/docs/site/pages/content/data-expressions.mdx b/docs/site/src/content/docs/content/data-expressions.mdx
similarity index 84%
rename from docs/site/pages/content/data-expressions.mdx
rename to docs/site/src/content/docs/content/data-expressions.mdx
index 988d9fabd..1552a54b6 100644
--- a/docs/site/pages/content/data-expressions.mdx
+++ b/docs/site/src/content/docs/content/data-expressions.mdx
@@ -2,11 +2,11 @@
title: Data & Expressions
---
-# Data
+## Data
Data is central to a lot of the functionality and features of Player. The easiest way to deal with data is to supply it in the initial payload when starting a flow. This will _seed_ the model with data and allow you to easily reference values
-## Bindings
+### Bindings
A binding is a representation of a path within the data-model. In simple terms, it's a dot (`.`) separated string showing the path of the properties within the data object.
@@ -39,7 +39,7 @@ For most bindings, it is recommended to use the dot-notation for all properties
Note that you can also use integers to access into arrays in the data model. `foo.bar.array.0.property` will reference `"another value"`.
-### Query Syntax
+#### Query Syntax
Bindings also allow for query access into arrays using a `key`/`value` pair to find the first matching item in the array.
@@ -50,16 +50,16 @@ data: {
model: {
array: [
{
- name: 'alpha',
- foo: 'bar',
+ name: "alpha",
+ foo: "bar",
},
{
- name: 'bravo',
- foo: 'baz',
+ name: "bravo",
+ foo: "baz",
},
{
- name: 'charlie',
- foo: 'qux',
+ name: "charlie",
+ foo: "qux",
},
];
}
@@ -76,7 +76,7 @@ Quotes around the key or the value of the query are only required when needing t
Note that the query syntax resolves to the object of the matching query, not to any specific property on the object. If you want to access a specific property, add additional path information after the query. E.g., `model.array[name=bravo].name`.
-### Nested Bindings
+#### Nested Bindings
Nested bindings allow you to construct a binding path that is relative to a 2nd path or based on some dynamic property. This behavior follows similar model lookup rules that can be used elsewhere in Player.
@@ -106,7 +106,7 @@ With this data model, `colors.{{favorite.color}}.hex` will return the hex value
References to bindings that contains sub-paths `{{favorite.nestedPath}}.hex` will expand to `colors.yellow.hex`.
-### Nested Expressions
+#### Nested Expressions
Just like binding segments can contain other bindings, segments can also contain expressions. For this, they use a segment surrounded by `:
@@ -122,15 +122,15 @@ Similar to the bracket notation: `[]`. Paths can use brackets instead of dots fo
colors[`getFavoriteColor()`].hex
```
-# Expressions
+## Expressions
Expressions are callable functions that allow for dynamic behavior of Player and it's views.
These functions can be used in `ACTION` nodes in the navigation section, calculated values in a property of an asset, or anywhere else expressions are valid.
-Check out the [Expression Plugin](../plugins/expression) for registering custom functions.
+Check out the [Expression Plugin](/plugins/core/expression) for registering custom functions.
-## Using Expressions and Data in a View
+### Using Expressions and Data in a View
Expressions in the view are strings wrapped in: `@[` and `]@`.
@@ -158,7 +158,7 @@ Data is referenced by wrapping the binding in `{{` and `}}`. This can be used in
Similar to expressions, any property only consisting of a data value lookup, will get replaced by the raw value.
-## Using Expressions for Inline Text Formatting
+### Using Expressions for Inline Text Formatting
`format` expression is used to replace provided value with appropriate format.
For instance, to format a number into `currency`, you may use:
@@ -169,45 +169,49 @@ For instance, to format a number into `currency`, you may use:
}
```
-To see the list of currently supported format types, check out [Common Types Plugin](../plugins/common-types.md).
+To see the list of currently supported format types, check out [Common Types Plugin](/plugins/core/common-types).
-## Built-in Expressions
+### Built-in Expressions
-There are a few expressions built into Player. These are pretty basic, so if you're looking for extend this -- check out the [Common Expressions Plugin](../plugins/common-expressions) or the [Expression Plugin](../plugins/expression) to add more.
+There are a few expressions built into Player. These are pretty basic, so if you're looking for extend this -- check out the [Common Expressions Plugin](/plugins/core/common-expressions) or the [Expression Plugin](/plugins/core/expression) to add more.
-| name | description | arguments |
-| --------------- | ------------------------------------------------------------------------------------- | ------------------ |
-| `getDataVal` | Fetches a value from the model. This is equivalent to using the `{{foo.bar}}` syntax. | `binding` |
-| `setDataVal` | Sets a value from the model. This is equivalent to using `{{foo.bar}} = 'value'` | `binding`, `value` |
-| `deleteDataVal` | Clears a value from the model. | `binding` |
+| name | description | arguments |
+| --------------- | ------------------------------------------------------------------------------------- | ------------------------------------------ |
+| `getDataVal` | Fetches a value from the model. This is equivalent to using the `{{foo.bar}}` syntax. | `binding` |
+| `setDataVal` | Sets a value from the model. This is equivalent to using `{{foo.bar}} = 'value'` | `binding`, `value` |
+| `deleteDataVal` | Clears a value from the model. | `binding` |
| `conditional` | Execute expressions, or return data based on an expression condition | `condition`, `valueIfTrue`, `valueIfFalse` |
-### Examples
+#### Examples
+
+##### `getDataVal`
-#### `getDataVal`
```json
{
"value": "Hello @[getDataVal('user.name')]@"
}
```
-#### `setDataVal`
+##### `setDataVal`
+
```json
{
"exp": "setDataVal('user.name', 'Test User')"
}
```
-#### `deleteDataVal`
+##### `deleteDataVal`
+
```json
{
"exp": "deleteDataVal('user.name')"
}
```
-#### `conditional`
+##### `conditional`
+
```json
{
"value": "It is @[ conditional({{foo.bar}} == 'DAY', 'daytime', 'nighttime') ]@."
}
-```
\ No newline at end of file
+```
diff --git a/docs/site/pages/content/index.mdx b/docs/site/src/content/docs/content/index.mdx
similarity index 98%
rename from docs/site/pages/content/index.mdx
rename to docs/site/src/content/docs/content/index.mdx
index e351cc0b9..8d219f196 100644
--- a/docs/site/pages/content/index.mdx
+++ b/docs/site/src/content/docs/content/index.mdx
@@ -1,9 +1,7 @@
---
-title: 'Content'
+title: "Content"
---
-# Content
-
Player is driven off of JSON content that describes the user interactions. It mainly consists of a state-machine, some views to drive display, data, and a schema. Player, once started with the JSON content, will _play_ the flow until it reaches a terminal state in the state-machine, and return the outcome, data, and other relevant information about the flow's execution.
The structure of the JSON payload is described below.
diff --git a/docs/site/pages/content/navigation.mdx b/docs/site/src/content/docs/content/navigation.mdx
similarity index 88%
rename from docs/site/pages/content/navigation.mdx
rename to docs/site/src/content/docs/content/navigation.mdx
index fdb040844..9c34bf3dc 100644
--- a/docs/site/pages/content/navigation.mdx
+++ b/docs/site/src/content/docs/content/navigation.mdx
@@ -2,7 +2,8 @@
title: Navigation
---
-# Navigation
+import Image from "../../../components/Image.astro";
+import simpleFlowImage from "../../../assets/simple-flow.png";
The `navigation` section of the content describes the path the user goes through as they progress. In simple terms, this can be thought of as a set of finite state machines, and the user progresses through each state until they hit a `DONE` node.
@@ -100,9 +101,9 @@ State types can also contain `onStart` and `onEnd` properties for evaluating exp
1. `onStart` - Evaluated at the start of a node's lifecycle; useful for updating data before it's resolved
2. `exp`
-3. `onEnd` - Evaluated last, right before transition.
- 1. For an `onEnd` expression defined on an individual state, if a transition is halted (by validation or otherwise), the `onEnd` expressions for that state won't be executed.
- 2. As Player's navigation is a state machine, `onEnd` expressions defined for the entire flow will only execute when the state machine ends the flow, by reaching an `END` state. Terminating the flow by unmounting Player (on any given platform) will not execute flow defined `onEnd` expressions as it would not have reached an `END` state.
+3. `onEnd` - Evaluated last, right before transition.
+ 1. For an `onEnd` expression defined on an individual state, if a transition is halted (by validation or otherwise), the `onEnd` expressions for that state won't be executed.
+ 2. As Player's navigation is a state machine, `onEnd` expressions defined for the entire flow will only execute when the state machine ends the flow, by reaching an `END` state. Terminating the flow by unmounting Player (on any given platform) will not execute flow defined `onEnd` expressions as it would not have reached an `END` state.
## Examples
@@ -130,7 +131,7 @@ State types can also contain `onStart` and `onEnd` properties for evaluating exp
This is the simplest of flows. The navigation begins with executing `FLOW_1`. `FLOW_1` begins with the `VIEW_1` state. `VIEW_1` shows the view with id `view-1`, and any transition from that view goes to `END_1` which completes Player's execution with the `Done` outcome.
-![Single Flow Example](/simple-flow.png?darkModeInvert)
+
### Flow with `onStart` expression on a `VIEW` state
diff --git a/docs/site/pages/content/schema.mdx b/docs/site/src/content/docs/content/schema.mdx
similarity index 92%
rename from docs/site/pages/content/schema.mdx
rename to docs/site/src/content/docs/content/schema.mdx
index 3530d73ee..b001b1ac3 100644
--- a/docs/site/pages/content/schema.mdx
+++ b/docs/site/src/content/docs/content/schema.mdx
@@ -2,8 +2,6 @@
title: Schema
---
-# Schema
-
The `schema` section of the content describes the relationship between the `view` and the `data`. It breaks down properties of the model's object into data-types, each with their own spot for validation, formatting, or default-values.
## Structure
@@ -43,13 +41,13 @@ Now the path `myProperty1.name` in the model points to a `StringType`. There are
## Data Types
-A `DataType` is a collection of the validation rules, formatting, and default values for a given path in the model. See the above [structure](#Structure) docs on how to author these in JSON content.
+A `DataType` is a collection of the validation rules, formatting, and default values for a given path in the model. See the above [structure](#structure) docs on how to author these in JSON content.
-As in the above `StringType` example, there are a number of pre-existing base types that can be utilized in the schema to describe a data type, and an extension mechanism for supplying additional base-types for use in the authored content. See the [types-provider-plugin](/plugins/types-provider) for an easy way to extend these.
+As in the above `StringType` example, there are a number of pre-existing base types that can be utilized in the schema to describe a data type, and an extension mechanism for supplying additional base-types for use in the authored content. See the [types-provider-plugin](/plugins/core/types-provider) for an easy way to extend these.
For any given path described by the schema, Player will merge the rules defined by the _base_ type (if one exists), and the rules defined specifically for that path in the authored content. Any custom formatter/default values take precedence over the default ones, and any custom validations are ran _before_ the base ones.
-Check out the [CommonTypes](/plugins/common-types) plugin for a list of easy to consume DataTypes for your application.
+Check out the [CommonTypes](/plugins/core/common-types) plugin for a list of easy to consume DataTypes for your application.
## Arrays
@@ -114,7 +112,7 @@ To attach a validation to a path in the data-model, add a reference to a validat
}
```
-Each _validation_ reference must include a `type` property which corresponds to the name of the validator to run. Player includes some validators out-of-the-box, and custom `validators` can be registered as well. See [the Common Types Plugin](../plugins/common-types) docs for more details around which validators are supported, and how to add custom ones.
+Each _validation_ reference must include a `type` property which corresponds to the name of the validator to run. Player includes some validators out-of-the-box, and custom `validators` can be registered as well. See [the Common Types Plugin](/plugins/core/common-types) docs for more details around which validators are supported, and how to add custom ones.
Any additional properties on the validation reference are passed as _options_ to the `validator`. In the example above, a hypothetical `length` validator can take a `min` and `max` as the boundaries for the length of a string.
diff --git a/docs/site/pages/guides/designing-semantic-assets.mdx b/docs/site/src/content/docs/guides/designing-semantic-assets.mdx
similarity index 76%
rename from docs/site/pages/guides/designing-semantic-assets.mdx
rename to docs/site/src/content/docs/guides/designing-semantic-assets.mdx
index 5a5f7cce3..6436b52e7 100644
--- a/docs/site/pages/guides/designing-semantic-assets.mdx
+++ b/docs/site/src/content/docs/guides/designing-semantic-assets.mdx
@@ -2,35 +2,33 @@
title: Designing Semantic Assets
---
-# Designing Semantic Assets
+While not a _hard_ requirement by Player, the API design for assets plays an important role in it's adoption, especially if the intent is to re-use content across platforms. In many cases, Player content is written, and edited many more times than assets are created, and thus it's schema plays an important role in it's effective adoption.
-While not a _hard_ requirement by Player, the API design for assets plays an important role in it's adoption, especially if the intent is to re-use content across platforms. In many cases, Player content is written, and edited many more times than assets are created, and thus it's schema plays an important role in it's effective adoption.
-
-Player ships with a set of [Reference Assets](../assets/reference) to get started, but intentionally doesn't include anything beyond some basics. We believe it's up to each consumer to define their own semantics (if at all), that best suites their applications.
+Player ships with a set of [Reference Assets](/assets/reference) to get started, but intentionally doesn't include anything beyond some basics. We believe it's up to each consumer to define their own semantics (if at all), that best suites their applications.
## Intent Based Schema
That being said, building off the learnings from using Player internally, we've developed a few guidelines and best practices for how we design asset APIs to help us scale effectively in our applications:
assets are described using their semantic intent regardless of their UI implementation
-* assets should leverage context, where applicable, to modify their behavior
+
+- assets should leverage context, where applicable, to modify their behavior
A prime example of an _intent_ based asset is a `choice`, which may have an API such as:
```ts
-interface ChoiceAsset extends Asset<'choice'> {
+interface ChoiceAsset extends Asset<"choice"> {
binding: Binding;
options: Array<{
id: string;
value: string;
label: TextAsset;
- }>
+ }>;
}
```
-Here we have a list of choices that a user may select from, the value of which is written to the provided binding.
-This may take the shape of a radio-group, select, or any number of other rendering options, but the platform specific asset implementations are able to derive the correct rendering without changing the content. The platform implementations may also want to query the asset's context as additional input into it's rendering -- i.e. if the `choice` is within a broader `form`, then render as a `select`.
+Here we have a list of choices that a user may select from, the value of which is written to the provided binding.
+This may take the shape of a radio-group, select, or any number of other rendering options, but the platform specific asset implementations are able to derive the correct rendering without changing the content. The platform implementations may also want to query the asset's context as additional input into it's rendering -- i.e. if the `choice` is within a broader `form`, then render as a `select`.
Using an intent based approach enables content to outlive design changes and the freedom for each platform to choose the best rendering mechanism for itself. It helps to avoid referencing colors/layouts/styles directly but provides additional _context_ to the assets when needed. (Supplying metaData to force a `chocie` to be compact).
-
diff --git a/docs/site/src/content/docs/guides/formatting.mdx b/docs/site/src/content/docs/guides/formatting.mdx
new file mode 100644
index 000000000..14976c004
--- /dev/null
+++ b/docs/site/src/content/docs/guides/formatting.mdx
@@ -0,0 +1,93 @@
+---
+title: Data Formatting and Deformatting
+---
+
+Formatting is simply a conversion (or middleware) for getting and setting data. It's often used to convey a different representation of the data to a user (like displaying a date).
+
+## References
+
+In order to attach a specific formatter to a part of the data-model, you need to supply a _reference_. These can be defined in the [schema](/content/schema) or a DataType.
+
+In either case, the reference to the applicable formatter looks identical:
+
+```json
+// An example of a formatter reference for a `date`
+{
+ "type": "date",
+ "format": "MM/DD/YYYY"
+}
+```
+
+The only _required_ property is the type. Any additional properties (`format` in this example) is passed to the formatter function as options. Not all formatters accept options, and they differ per format type.
+
+Each binding can be mapped to 1 format at most. Any reference set directly on an item in the schema, will override an inherited format from a parent type.
+
+## Formatting Lifecycle
+
+There are 2 main steps in the formatting lifecycle `formatting` and `deformatting`. Each format type may define either or both.
+
+Simply stated:
+
+- `formatting`: **Data Model** -> **User**
+- `deformatting`: **User** -> **Data Model**
+
+In cases where the data-type may change between the user and the data-model (think epoch to a formatted time, or integers to a comma number) you'll likely want to specify both, though either, both, or neither is also valid.
+
+## Using Formatted Data
+
+In order to get or set formatted values from the model, add `formatted: true` to the options of the data-model method. This is most often through the use of a [transform](/plugins/asset-transform).
+
+```javascript
+function assetTransform(value, options) {
+ return {
+ ...value,
+ formattedVersion: options.data.model.get('some binding', {
+ formatted: true,
+ }),
+ };
+}
+```
+
+This also works for setting data:
+
+```javascript
+options.data.model.set([['some binding', 'some value']], { formatted: true });
+```
+
+You can also use the `format` function directly from a transform:
+
+```javascript
+options.data.format('some binding', 'some value');
+```
+
+Using the `format` function will not mutate any data in the model.
+
+## Defining Custom formats
+
+### Creating a format-type
+
+A custom format-type is defined by an object with a `name`, an optional `format` handler, and an optional `deformat` handler.
+
+Each `format` or `deformat` function takes a `value` and some `options` (those defined in the format reference) and returns a new value to use. Format handlers should not contain any side-effects as they can be ran multiple times and are expected to be pure functions.
+
+### Registering a custom format
+
+The easiest way to add the custom format to the player is through the `types-provider` plugin.
+
+Create your format object, and add register it with the plugin:
+
+```javascript
+import { TypesProviderPlugin } from '@player-ui/types-provider-plugin';
+
+const provider = new TypesProviderPlugin({
+ formats: [
+ {
+ name: 'custom-formatter',
+ format: () => 'formatted-value',
+ deformat: () => 'deformatted-value',
+ },
+ ],
+});
+```
+
+Now any DataType or schema reference to `custom-formatter` will use this handler.
diff --git a/docs/site/pages/getting-started.mdx b/docs/site/src/content/docs/guides/getting-started.mdx
similarity index 77%
rename from docs/site/pages/getting-started.mdx
rename to docs/site/src/content/docs/guides/getting-started.mdx
index 87f0c26b2..dee681351 100644
--- a/docs/site/pages/getting-started.mdx
+++ b/docs/site/src/content/docs/guides/getting-started.mdx
@@ -1,8 +1,8 @@
---
-title: 'Getting Started'
+title: "Getting Started"
---
-# Getting Started
+import PlatformTabs from "../../../components/PlatformTabs.astro";
Getting started with Player is simple.
@@ -11,7 +11,7 @@ Getting started with Player is simple.
The first dependency you'll need to pull in is the Player itself. Additionally, you'll need an assets plugin to define any UI -- we'll use the reference assets as an example.
-
+
You can do this by running
@@ -26,8 +26,9 @@ or
npm install @player-ui/react
npm install @player-ui/reference-assets-plugin-react
```
-
-
+
+
+
In your `Podfile` you'll need to add `PlayerUI` as a dependency and the `ReferenceAssets` plugin to use the base set of assets.
@@ -40,8 +41,9 @@ target 'MyApp' do
pod 'PlayerUI/ReferenceAssets' # For example only
end
```
-
-
+
+
+
Configure the Android Player dependencies in your `build.gradle(.kts)` files.
@@ -73,21 +75,24 @@ buildTypes {
}
}
```
-
+
+
-
+:::caution
+The reference assets aren't intended for production use. They exist as an example of how to create assets and can be used to help get started.
+:::
### Configuration
Next, in your code you'll need to initialize Player. This is where you would also initialize any plugins you want to use with Player and create the configuration for Player itself. Below is a minimal example of this.
-
+
```javascript
-import { ReactPlayer } from '@player-ui/react';
-import { ReferenceAssetsPlugin } from '@player-ui/reference-assets-plugin-react';
+import { ReactPlayer } from "@player-ui/react";
+import { ReferenceAssetsPlugin } from "@player-ui/reference-assets-plugin-react";
// create a new web-player instance
@@ -95,8 +100,9 @@ const reactPlayer = new ReactPlayer({
plugins: [new ReferenceAssetsPlugin()],
});
```
-
-
+
+
+
`SwiftUIPlayer` is just a normal SwiftUI View and can be inserted anywhere in your hierarchy.
@@ -109,9 +115,10 @@ var body: some View {
)
}
```
-
-
+
+
+
```kotlin
// create Android Player with reference assets plugin
@@ -122,24 +129,29 @@ val player = AndroidPlayer(
)
)
```
+
Apart from providing a list of plugins while setting up `AndroidPlayer`, you can also provide a `config` object that has the following options:
- - `debuggable` - Indicates if the runtime is debuggable on android through chromium devtools, enabling this would let you set breakpoints in js code as you're running it on android.
- - `coroutineExceptionHandler` - [CoroutineExceptionHandler](https://kotlinlang.org/docs/exception-handling.html#coroutineexceptionhandler) should handle all uncaught exceptions while using the runtime coroutine scope.
- - `timeout` - Timeout for the JS thread. If none is provided then it is set as `if (debuggable) Int.MAX_VALUE.toLong() else 5000`.
+- `debuggable` - Indicates if the runtime is debuggable on android through chromium devtools, enabling this would let you set breakpoints in js code as you're running it on android.
+- `coroutineExceptionHandler` - [CoroutineExceptionHandler](https://kotlinlang.org/docs/exception-handling.html#coroutineexceptionhandler) should handle all uncaught exceptions while using the runtime coroutine scope.
+- `timeout` - Timeout for the JS thread. If none is provided then it is set as `if (debuggable) Int.MAX_VALUE.toLong() else 5000`.
+
+
-
### Render Content
+
Now that you have a Player instance created. You'll need to start it with some [content](/content).
-
+
```javascript
-const content = {/* your content here */}
+const content = {
+ /* your content here */
+};
reactPlayer.start(content);
```
@@ -150,8 +162,9 @@ const MyApp = () => {
return ;
};
```
-
-
+
+
+
Expanding on the `SwiftUIPlayer` creation above, providing a `flow` will start the Player automatically, and the `result` will update the `Binding?>` that you pass to it:
@@ -170,8 +183,9 @@ struct MyApp: View {
}
}
```
-
-
+
+
+
To receive view updates, you must add a handler to render the views which are represented as `RenderableAsset`s.
@@ -192,7 +206,7 @@ When you're done with Player, release any native runtime memory used to instanti
player.release()
```
-Creating your own `AndroidPlayer` instance is fairly simple, but it grows in complexity when considering proper resources management and app orchestration. We provide a Fragment/ViewModel integration to make it easier to properly integrate into your app and account for these concerns.
+Creating your own `AndroidPlayer` instance is fairly simple, but it grows in complexity when considering proper resources management and app orchestration. We provide a Fragment/ViewModel integration to make it easier to properly integrate into your app and account for these concerns.
#### ViewModel
@@ -228,13 +242,15 @@ As the core Player is written in TypeScript, we need a JVM compatible JavaScript
To support a specific runtime implementation, there needs to be code connecting the runtime constructs to the Player runtime abstraction. The Player project has implemented this layer for several runtimes, described below. It is possible to define your own, but the abstraction definition is not yet final, and therefore not appropriately documented. You can take inspiration from the existing implementations, or file an issue for a runtime you wish to see supported by our team.
-| Runtimes | Platforms |
-| -------- | --------- |
+| Runtimes | Platforms |
+| --------------------------------------------- | --------------------------- |
| [J2V8](https://github.com/eclipsesource/J2V8) | `android`, `linux`, `macos` |
-| [Hermes](https://github.com/facebook/hermes) | `android` |
-| [GraalJS](https://github.com/oracle/graaljs) | `linux`, `macos`, `win` |
+| [Hermes](https://github.com/facebook/hermes) | `android` |
+| [GraalJS](https://github.com/oracle/graaljs) | `linux`, `macos`, `win` |
-
+:::note
+Each of the artifacts for the above are defined as `com.intuit.playerui:$runtime-$platform`, i.e. `com.intuit.playerui:j2v8-android`
+:::
The `HeadlessPlayer` does not define a hard dependency on any specific runtime, however, the `AndroidPlayer` does transitively depends on the `j2v8` runtime, as the first class approach. To override, the transitive dependency would need to be explicitly excluded and the actual runtime dependency would need to be added:
@@ -252,9 +268,11 @@ dependencies {
}
```
-
-
-
+:::caution
+If your application includes dependencies that may transitively depend on `com.intuit.playerui:android`, you would likely need to ensure the default runtime is transitively excluded from those as well, either manually or as a global strategy.
+:::
-Congrats! You've got Player up and running. If you need additional functionality you can add more plugins to extend Player's functionality. Head over to the [Plugins](./plugins) section to take a look at the Plugins we've developed or take a look at the [Architecture](./architecture) section to see how you can write your own.
+
+
+Congrats! You've got Player up and running. If you need additional functionality you can add more plugins to extend Player's functionality. Head over to the [Plugins](/plugins) section to take a look at the Plugins we've developed or take a look at the [Architecture](./architecture) section to see how you can write your own.
\ No newline at end of file
diff --git a/docs/site/pages/guides/multi-flow-experiences.mdx b/docs/site/src/content/docs/guides/multi-flow-experiences.mdx
similarity index 75%
rename from docs/site/pages/guides/multi-flow-experiences.mdx
rename to docs/site/src/content/docs/guides/multi-flow-experiences.mdx
index d11a9ebfc..ba19cf709 100644
--- a/docs/site/pages/guides/multi-flow-experiences.mdx
+++ b/docs/site/src/content/docs/guides/multi-flow-experiences.mdx
@@ -2,16 +2,17 @@
title: Multi-Flow Experiences
---
-# Multi-Flow Experiences
-
-One large use-case for Player involves orchestrating experiences that span multiple screens that may need to communicate with a back-end between stages. This is commonly used for stepped-flows, onboarding workflows, etc, and manifests as using the response from one Player flow to determine the next one. To facilitate this back-and-forth, Player ships with support for creating a flow-manager.
+import PlatformTabs from "../../../components/PlatformTabs.astro";
+import Image from "../../../components/Image.astro";
+import flowManagerImage from "../../../assets/flow-manager.png";
+One large use-case for Player involves orchestrating experiences that span multiple screens that may need to communicate with a back-end between stages. This is commonly used for stepped-flows, onboarding workflows, etc, and manifests as using the response from one Player flow to determine the next one. To facilitate this back-and-forth, Player ships with support for creating a flow-manager.
## Flow Manager
-A flow-manager is an interface for asynchronously stepping through a series of flows in a multi-flow experience. Its API mirrors that of the JavaScript [iteration protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols); each flow is loaded by calling `.next()` using the result of the previous flow (if one exists). Implementations are able to leverage this response to retrieve the _next_ flow in the series, or mark the cycle as complete by returning `done`.
+A flow-manager is an interface for asynchronously stepping through a series of flows in a multi-flow experience. Its API mirrors that of the JavaScript [iteration protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols); each flow is loaded by calling `.next()` using the result of the previous flow (if one exists). Implementations are able to leverage this response to retrieve the _next_ flow in the series, or mark the cycle as complete by returning `done`.
-![Flow Manager](/flow-manager.png?darkModeInvert)
+
The standardization of this contract allows any client to manage a series of Player flows without needing to repeat the underlying Player-side orchestration.
@@ -35,47 +36,47 @@ interface FlowManager {
}
```
-Shown above is also an optional `terminate` callback. This is used when a flow is ended prematurely (user closes a view) as a means of gathering any critical information from the running player before shutting down.
+Shown above is also an optional `terminate` callback. This is used when a flow is ended prematurely (user closes a view) as a means of gathering any critical information from the running player before shutting down.
## Managed Player
-
+
-The `ManagedPlayer` component from the `@player-ui/react` module orchestrates running flows through Player using a provided `flow-manager`. Any provided configuration/plugins will be passed along to the underlying `ReactPlayer` instance, and `React.Suspense` is used while awaiting the next `flow-manager` response.
+The `ManagedPlayer` component from the `@player-ui/react` module orchestrates running flows through Player using a provided `flow-manager`. Any provided configuration/plugins will be passed along to the underlying `ReactPlayer` instance, and `React.Suspense` is used while awaiting the next `flow-manager` response.
-Simply render the `ManagedPlayer` with a flow-manager:
+Simply render the `ManagedPlayer` with a flow-manager:
```tsx
-import { ManagedPlayer } from '@player-ui/react';
+import { ManagedPlayer } from "@player-ui/react";
export const App = () => {
- return
-}
+ return ;
+};
```
### Callbacks and Error Handling
-The `ManagedPlayer` also includes callbacks for `onComplete` and `onError` to handle the completion of a multi-flow experience.
+The `ManagedPlayer` also includes callbacks for `onComplete` and `onError` to handle the completion of a multi-flow experience.
-The `fallbackComponent` is an optional prop that accepts a React component that will be rendered in case of an error. It's given access to the thrown `Error` object, as well as a `retry` and `reset` callback:
+The `fallbackComponent` is an optional prop that accepts a React component that will be rendered in case of an error. It's given access to the thrown `Error` object, as well as a `retry` and `reset` callback:
-* `retry` -- Retries the last failed request (the last call to `next()`)
-* `reset` -- Restarts the multi-flow from the begining, calling `next()` with an empty context.
+- `retry` -- Retries the last failed request (the last call to `next()`)
+- `reset` -- Restarts the multi-flow from the begining, calling `next()` with an empty context.
+
+
-
-
-
-The `ManagedPlayer` SwiftUI Component from the `PlayerUI/SwiftUI` subspec orchestrates running flows through Player using a provided `FlowManager`. Any provided configuration or plugins are passed along to the underlying `SwiftUIPlayer` instance.
+The `ManagedPlayer` SwiftUI Component from the `PlayerUI/SwiftUI` subspec orchestrates running flows through Player using a provided `FlowManager`. Any provided configuration or plugins are passed along to the underlying `SwiftUIPlayer` instance.
When constructing the `ManagedPlayer` you supply views to be used for error scenarios, as well as what is displayed while the FlowManager is fetching flows.
### Error Handling
+
The `fallback` parameter receives a `ManagedPlayerErrorContext` object when called, this object contains the `Error` that was thrown, as well as `retry` and `reset` functions.
-* `retry` -- Retries the last failed request (the last call to `next()`)
-* `reset` -- Restarts the multi-flow from the begining, calling `next()` with an empty context.
+- `retry` -- Retries the last failed request (the last call to `next()`)
+- `reset` -- Restarts the multi-flow from the begining, calling `next()` with an empty context.
```swift
import PlayerUI
@@ -93,5 +94,5 @@ struct App: View {
}
```
-
+
diff --git a/docs/site/pages/plugin-implementation.mdx b/docs/site/src/content/docs/guides/plugin-implementation.mdx
similarity index 69%
rename from docs/site/pages/plugin-implementation.mdx
rename to docs/site/src/content/docs/guides/plugin-implementation.mdx
index 575c46d25..be93d4704 100644
--- a/docs/site/pages/plugin-implementation.mdx
+++ b/docs/site/src/content/docs/guides/plugin-implementation.mdx
@@ -2,11 +2,9 @@
title: Plugin Implementation
---
-# Plugin Implementation
-
The main purpose of a Plugin is to extend or add new functionality by tapping into Player's pipeline of components via hooks. In this section we'll go over the steps to implement a plugin.
-We'll use the [stage-revert-data](./plugins/stage-revert-data) plugin as example. After creating our plugin class, we'll use the `apply` method which provides access to the Player instance, which then gives access to the necessary hooks.
+We'll use the [stage-revert-data](/plugins/core/stage-revert-data) plugin as example. After creating our plugin class, we'll use the `apply` method which provides access to the Player instance, which then gives access to the necessary hooks.
```typescript
export default class StageRevertDataPlugin implements PlayerPlugin {
@@ -29,7 +27,9 @@ export default class StageRevertDataPlugin implements PlayerPlugin {
{ shouldIncludeInvalid: () => true }
);
```
+
For this case we needed to define variables that will store references for the scope the hooks will share:
+
- `dataController`: Reference to the data controller hook in the Player instance, can be used to read, update or commit new changes to the data model
- `stageData`: View attribute that comes from the view state, used for enabling the staging of data
- `commitTransitions`: The list of view names which the shadow model should be committed if transitioned to. Comes from the view state attribute as well.
@@ -39,54 +39,56 @@ For this case we needed to define variables that will store references for the s
The next step is to tap into the necessary Player hooks. First we tap into the `viewController` which we can then intercept the `resolveView` hook. Player hooks are implemented with the [Tapable](https://github.com/webpack/tapable) package, so we can use the interception API's `call` method, this triggers everytime the hook is triggered, then we get access to the current view state and read the `stageData` and `commitTransitions` attributes.
```typescript
- player.hooks.viewController.tap(this.name, (vc) => {
- vc.hooks.resolveView.intercept({
- call: (view, id, state) => {
- stageData = state?.attributes?.stageData;
- commitTransitions = state?.attributes?.commitTransitions;
- },
- });
- });
+player.hooks.viewController.tap(this.name, (vc) => {
+ vc.hooks.resolveView.intercept({
+ call: (view, id, state) => {
+ stageData = state?.attributes?.stageData;
+ commitTransitions = state?.attributes?.commitTransitions;
+ },
+ });
+});
```
+
`Note`: notice how each time we tap into a hook, we use the `this.name` property as the name of the plugin. This is important to avoid conflicts with other plugins.
Next we tap into the `dataController`, so we can scope the data controller instance for future use. Then we tap into the `resolveDataStages` plugin in this data controller instance. If the `stage` property is set to true, we add our `GatedDataMiddleware` to the data pipeline. If not, we return the data pipeline as is.
```typescript
- player.hooks.dataController.tap(this.name, (dc: DataController) => {
- dataController = dc;
-
- dc.hooks.resolveDataStages.tap(this.name, (dataPipeline) => {
- return stageData
- ? [...dataPipeline, GatedDataMiddleware]
- : [...dataPipeline];
- });
- });
+player.hooks.dataController.tap(this.name, (dc: DataController) => {
+ dataController = dc;
+
+ dc.hooks.resolveDataStages.tap(this.name, (dataPipeline) => {
+ return stageData
+ ? [...dataPipeline, GatedDataMiddleware]
+ : [...dataPipeline];
+ });
+});
```
+
Finally, we tap into the `flowController` so we can intercept the `flow` hook. We then tap into the `transition` hook, which is called every time the player transitions from one view to another. If the `commitTransitions` includes the next view name, we set the `commitShadowModel` flag to true, and commit the data stored in the shadow model through `GatedDataMiddleware` into the data model. Whether the data was committed from the shadow model or not, we clear the shadow model paths in the `GatedDataMiddleware` instance and set the `commitShadowModel` flag to false as final steps.
```typescript
- player.hooks.flowController.tap(this.name, (flowController) => {
- flowController.hooks.flow.tap(this.name, (flow) => {
- flow.hooks.transition.tap(this.name, (from, to) => {
- if (from) {
- if (commitTransitions.includes(to.name)) {
- commitShadowModel = true;
- player.logger.debug(
- 'Shadow Model Data to be committed %s',
- GatedDataMiddleware.shadowModelPaths
- );
- dataController.set(GatedDataMiddleware.shadowModelPaths);
- }
-
- commitShadowModel = false;
- GatedDataMiddleware.shadowModelPaths.clear();
- }
- });
- });
+player.hooks.flowController.tap(this.name, (flowController) => {
+ flowController.hooks.flow.tap(this.name, (flow) => {
+ flow.hooks.transition.tap(this.name, (from, to) => {
+ if (from) {
+ if (commitTransitions.includes(to.name)) {
+ commitShadowModel = true;
+ player.logger.debug(
+ "Shadow Model Data to be committed %s",
+ GatedDataMiddleware.shadowModelPaths,
+ );
+ dataController.set(GatedDataMiddleware.shadowModelPaths);
+ }
+
+ commitShadowModel = false;
+ GatedDataMiddleware.shadowModelPaths.clear();
+ }
});
+ });
+});
```
And this is how we implement a plugin that manages the staging of data based on the view state attributes.
-Code Snippets Reference: [StageRevertDataPlugin](https://github.com/player-ui/player/blob/main/plugins/stage-revert-data/core/src/index.ts)
\ No newline at end of file
+Code Snippets Reference: [StageRevertDataPlugin](https://github.com/player-ui/player/blob/main/plugins/stage-revert-data/core/src/index.ts)
diff --git a/docs/site/pages/writing-plugins.mdx b/docs/site/src/content/docs/guides/writing-plugins.mdx
similarity index 90%
rename from docs/site/pages/writing-plugins.mdx
rename to docs/site/src/content/docs/guides/writing-plugins.mdx
index d6c93b18b..51be375f6 100644
--- a/docs/site/pages/writing-plugins.mdx
+++ b/docs/site/src/content/docs/guides/writing-plugins.mdx
@@ -1,17 +1,16 @@
---
-title: Player Team
+title: Writing a Plugin
platform: core,react
---
-# Writing a Plugin
-
- While we have published a majority of the plugins we have developed, there will always be new use cases that may require new functionality. Writing a plugin in the easiest way to extend Player functionality for these cases. Plugins work slightly differently on each platform so in this guide we will cover how to write a plugin for each platform.
+import PlatformTabs from "../../../components/PlatformTabs.astro";
+While we have published a majority of the plugins we have developed, there will always be new use cases that may require new functionality. Writing a plugin in the easiest way to extend Player functionality for these cases. Plugins work slightly differently on each platform so in this guide we will cover how to write a plugin for each platform.
-
+
-Core plugins are the easiest way to extend Player functionality regardless of what platform you are using Player on. To make writing core plugins easy `@player-ui/player` exposes an interface `PlayerPlugin` that denotes everything needed. The two mandatory features are a `name` property which is lets Player know how to refer to the plugin and an implemented `apply` function that takes a `player` object. Optionally a `symbol` property can be used to provide a unique identifier that can be used to retrieve the plugin from Player.
+Core plugins are the easiest way to extend Player functionality regardless of what platform you are using Player on. To make writing core plugins easy `@player-ui/player` exposes an interface `PlayerPlugin` that denotes everything needed. The two mandatory features are a `name` property which is lets Player know how to refer to the plugin and an implemented `apply` function that takes a `player` object. Optionally a `symbol` property can be used to provide a unique identifier that can be used to retrieve the plugin from Player.
The first step for creating a plugin is making our plugin class, making sure it implements the `PlayerPlugin` interface from `@player-ui/player`. By convention, a name attribute with the dash-cased name of your plugin should be defined.
@@ -29,7 +28,7 @@ export default class ExamplePlayerPlugin implements PlayerPlugin {
}
```
-The `apply` function is where the actual logic of the plugin lives. By tapping the hooks exposed via `player.hooks` you gain access to the internal pipeline of components that comprise Player and can inject your functionality into their exposed hooks. For example if you want to do something any time Player's state changes you could do the following:
+The `apply` function is where the actual logic of the plugin lives. By tapping the hooks exposed via `player.hooks` you gain access to the internal pipeline of components that comprise Player and can inject your functionality into their exposed hooks. For example if you want to do something any time Player's state changes you could do the following:
```javascript
apply(player: Player) {
@@ -40,6 +39,7 @@ apply(player: Player) {
```
Some components expose hooks themselves which may require multiple levels of taps which is not uncommon. For example if you wanted to modify the `ViewInstance` before it was resolved you would do the following:
+
```javascript
apply(player: Player) {
player.hooks.viewController.tap(this.name, (vc) => {
@@ -50,20 +50,20 @@ apply(player: Player) {
}
```
-It is not uncommon for core plugins to have constructors for cases where the plugin needs to take some configuration. In cases where plugin configs are more complicated than basic feature flags, it is recommended to make an interface to represent the config object. As an added benefit it also makes it easier to down stream consumers to use your plugin.
+It is not uncommon for core plugins to have constructors for cases where the plugin needs to take some configuration. In cases where plugin configs are more complicated than basic feature flags, it is recommended to make an interface to represent the config object. As an added benefit it also makes it easier to down stream consumers to use your plugin.
-For a more comprehensive guide on plugins, check out this [Plugin Implementation](./plugin-implementation) example.
+For a more comprehensive guide on plugins, check out this [Plugin Implementation](/guides/plugin-implementation) example.
_Note: For the React Player you can import and load the plugin the same way you would a React Player Plugin but for the iOS and Android Players you will need to wrap the javascript bundle in a iOS/Android plugin to ensure it is available on your platform._
-
-
+
+
React Player Plugins are very similar to core plugins in both their composition and use. The `@player-ui/react` package exposes an interface `ReactPlayerPlugin` that, much like the `PlayerPlugin` interface provides the necessary attributes that are required for a React Player plugin. Again a dash-cased `name` attribute should be used by convention, and a function `applyReact` is required that takes a `ReactPlayer` instance. Similarly to core plugins in the `applyReact` function you have access to the React Player object and access to the three exposed hooks:
-- The `webComponent` hook allows you to modify a React component that is stored in the React Player for use when it renders content. This happens during the initialization phase and ise useful if you want to wrap components in various content providers.
-- The `playerComponent` hook allows you to modify a component or execute functionality when the React Player is rendering a component after the view has been reconciled in Player. This is useful if you want to inject additional props to components or collect data on which component was rendered.
-- The `onBeforeViewReset` hook is fired when the view is resetting to undefined and you want to execute some asynchronous tasks.
+- The `webComponent` hook allows you to modify a React component that is stored in the React Player for use when it renders content. This happens during the initialization phase and ise useful if you want to wrap components in various content providers.
+- The `playerComponent` hook allows you to modify a component or execute functionality when the React Player is rendering a component after the view has been reconciled in Player. This is useful if you want to inject additional props to components or collect data on which component was rendered.
+- The `onBeforeViewReset` hook is fired when the view is resetting to undefined and you want to execute some asynchronous tasks.
Below is an example of a basic `ReactPlayerPlugin` that would expose a function to every component that gets loaded in the React Player:
@@ -101,11 +101,11 @@ export class FunctionPlugin implements ReactPlayerPlugin {
}
```
-Lastly React plugins can also act as a core plugin in cases where core functionality needs to be extended for the React plugin to work. Since both the `PlayerPlugin` and `ReactPlayerPlugin` are typescript interfaces a plugin can implement both and be considered a valid plugin.
+Lastly React plugins can also act as a core plugin in cases where core functionality needs to be extended for the React plugin to work. Since both the `PlayerPlugin` and `ReactPlayerPlugin` are typescript interfaces a plugin can implement both and be considered a valid plugin.
-
-
-iOS Player Plugins are very similar to core and react plugins in both their composition and use.
+
+
+iOS Player Plugins are very similar to core and react plugins in both their composition and use.
### NativePlugin
@@ -116,8 +116,8 @@ The `player` passed to `apply` exposes hooks from the core player, as well as ho
- The `view` hook allows you to modify the root view that will be displayed in the SwiftUIPlayer body. This is useful for applying changes to the environment for the SwiftUI view tree, or apply ViewModifiers and such.
- The `transition` hook allows you to specify a `PlayerViewTransition` object to be applied when the flow transitions from one view to another, to animate the transition.
-
#### Basic Example
+
Below is an example of a basic `NativePlugin` that sets a value in the EnvironmentValues when the plugin is included:
```swift
@@ -134,7 +134,9 @@ class EnvironmentPlugin: NativePlugin {
}
}
```
+
#### Asset Registration
+
Likely the most common usecase for plugins is to register assets:
```swift
@@ -152,11 +154,13 @@ class ExampleAssetPlugin: NativePlugin {
```
### JSBasePlugin
-Building native features on top of shared functionality is one of the primary benefits of using player. As such we expose convenience utilities to enable loading JavaScript Player Plugins as the base for your `NativePlugin`.
+Building native features on top of shared functionality is one of the primary benefits of using player. As such we expose convenience utilities to enable loading JavaScript Player Plugins as the base for your `NativePlugin`.
#### Basic Setup
+
This example will load the `SharedJSPlugin` in the JavaScript layer when included as a plugin to `SwiftUIPlayer`.
+
```swift
import PlayerUI
@@ -177,7 +181,9 @@ class SharedJSPlugin: JSBasePlugin {
}
}
```
+
#### Arguments for constructing the JavaScript plugins
+
To simplify the ease of use, the `JSContext` for `JSBasePlugin` implementations is provided when the underlying resources for the core `player` are being setup. This means that we need to provide the arguments for the JavaScript constructor late. To do this, override the `getArguments` function:
```swift
@@ -203,7 +209,7 @@ class SharedJSPlugin: JSBasePlugin {
**Note**: As `JavaScriptCore` cannot resolve dependencies at runtime, using a module bundler such as [tsup](https://github.com/egoist/tsup) is required.
-**Note**: `JSBasePlugin` implementations do not necessarily need to be a `PlayerPlugin`, for example, the [BeaconPlugin](https://github.com/player-ui/player/blob/main/ios/plugins/BaseBeaconPlugin/Sources/BaseBeaconPlugin.swift#L63) can take plugins in it's constructor, that are not `PlayerPlugin`.
+**Note**: `JSBasePlugin` implementations do not necessarily need to be a `PlayerPlugin`, for example, the [BeaconPlugin](https://github.com/player-ui/player/blob/main/plugins/beacon/ios/Sources/BaseBeaconPlugin.swift#L59) can take plugins in it's constructor, that are not `PlayerPlugin`.
-
+
diff --git a/docs/site/src/content/docs/index.mdx b/docs/site/src/content/docs/index.mdx
new file mode 100644
index 000000000..46fc9f2f7
--- /dev/null
+++ b/docs/site/src/content/docs/index.mdx
@@ -0,0 +1,55 @@
+---
+title: Player
+description: Get started building your docs site with Starlight.
+template: splash
+hero:
+ tagline: A cross-platform semantic rendering engine
+ image:
+ file: ../../assets/logo/logo-dark-small.png
+ actions:
+ - text: Learn More
+ link: /player/about
+ icon: information
+ - text: Get Started
+ link: /guides/getting-started/
+ icon: right-arrow
+ variant: minimal
+---
+
+import { Card, CardGrid } from "@astrojs/starlight/components";
+import Image from "../../components/Image.astro";
+import playerPlatformDiagram from "../../assets/platform_diagram.png";
+import PlayerPreview from "../../components/PlayerPreview.astro";
+
+
+
+## Why Player?
+
+
+
+ Sharing content across platforms enables you to quickly release new
+ features, on all platforms, with just a simple content deployment.
+
+
+ Player works seamlessly with your existing UI components to fit application.
+ Define your own patterns through assets and render them exactly as your
+ designers intended.
+
+
+ Need to figure out where go next? Chaining multiple pages together with
+ Player is a breeze. Check out the [docs](/guides/multi-flow-experiences) for
+ more details.
+
+
+ Player is designed from the ground up with plugins in mind. [Read
+ more](/plugins/) about the 20+ provided plugins, or how to write your own.
+
+
+
+## What does it look like?
+
+
diff --git a/docs/site/pages/about.mdx b/docs/site/src/content/docs/player/about.mdx
similarity index 83%
rename from docs/site/pages/about.mdx
rename to docs/site/src/content/docs/player/about.mdx
index 967ba4d6c..9bda6f259 100644
--- a/docs/site/pages/about.mdx
+++ b/docs/site/src/content/docs/player/about.mdx
@@ -2,19 +2,24 @@
title: About
---
-![Player Logo](/logo/logo-light-large.png?lightModeOnly)
-![Player Logo](/logo/logo-dark-large.png?darkModeOnly)
+import Image from "../../../components/Image.astro";
+import darkLogo from "../../../assets/logo/logo-dark-large.png";
+import lightLogo from "../../../assets/logo/logo-light-large.png";
+
+
## What Is Player?
-What is Player? Simply put, Player is a framework that enables users to natively render experiences across multiple platforms via a declarative content payload. At Intuit engineers use Player to accelerate the development of new experiences as Player allows them offload data/state management and fit seamlessly with other applications all with minimal configuration.
+What is Player? Simply put, Player is a framework that enables users to natively render experiences across multiple platforms via a declarative content payload. At Intuit engineers use Player to accelerate the development of new experiences as Player allows them offload data/state management and fit seamlessly with other applications all with minimal configuration.
## Why Did We Build It?
-Player is the second iteration of this kind of framework. The first iteration that was developed for internal use and worked well but had its limitations. With limited extensibility, limited platform support, and no type support the framework stated to rapidly show its age as we tried to move into newer spaces. It was then determined that we needed to take our learnings from the past few years and rearchitect it from the ground up. And that's how we got Player.
+
+Player is the second iteration of this kind of framework. The first iteration that was developed for internal use and worked well but had its limitations. With limited extensibility, limited platform support, and no type support the framework stated to rapidly show its age as we tried to move into newer spaces. It was then determined that we needed to take our learnings from the past few years and rearchitect it from the ground up. And that's how we got Player.
## What Makes It Special?
-The first of the big changes with Player was using TypeScript over vanilla JavaScript. By leveraging TypeScript's strong typing system, we not only made it easier and safer to work on Player, but we were also able to expose our internal types in an easily consumable format. This paves the way for external tooling to be developed around Player.
-Now the biggest feature of Player: Plugins. This is discussed more in the Architecture section but at a high level, almost every component of Player exposes entry points to extend its functionality to make it work for your use case. We have included a handful of plugins we've developed alongside player but if none of those do what you need, the blueprint is there to build your own.
+The first of the big changes with Player was using TypeScript over vanilla JavaScript. By leveraging TypeScript's strong typing system, we not only made it easier and safer to work on Player, but we were also able to expose our internal types in an easily consumable format. This paves the way for external tooling to be developed around Player.
+
+Now the biggest feature of Player: Plugins. This is discussed more in the Architecture section but at a high level, almost every component of Player exposes entry points to extend its functionality to make it work for your use case. We have included a handful of plugins we've developed alongside player but if none of those do what you need, the blueprint is there to build your own.
-Lastly, Player has iOS and JVM/Android clients. On these platforms you can create native experiences with minimal overhead and not just render a web view. Components can also be written in their native language allow someone with zero web dev experience to use Player.
+Lastly, Player has iOS and JVM/Android clients. On these platforms you can create native experiences with minimal overhead and not just render a web view. Components can also be written in their native language allow someone with zero web dev experience to use Player.
diff --git a/docs/site/pages/faqs.mdx b/docs/site/src/content/docs/player/faqs.mdx
similarity index 75%
rename from docs/site/pages/faqs.mdx
rename to docs/site/src/content/docs/player/faqs.mdx
index 05516cfeb..86ac16efb 100644
--- a/docs/site/pages/faqs.mdx
+++ b/docs/site/src/content/docs/player/faqs.mdx
@@ -2,31 +2,35 @@
title: FAQs
---
-# Frequently Asked Questions
-
## How much do I need to know about Player to use it?
-While it definitely helps to understand how it works under the hood, as long as you understand the how [Assets & Views](./content/assets-views), [Data & Expressions](./content/data-expressions), and [Navigation](./content/navigation) works you should be ready to author Player content.
-If you are an engineer integrating Player into your experience you should probably be familiar with what [Plugins](./plugins) are available and how to [write your own](./writing-plugins) to support the folks who will be authoring the content. The more advanced your use case is you can explore topics as they become applicable.
+While it definitely helps to understand how it works under the hood, as long as you understand the how [Assets & Views](/content/assets-views), [Data & Expressions](/content/data-expressions), and [Navigation](/content/navigation) works you should be ready to author Player content.
+
+If you are an engineer integrating Player into your experience you should probably be familiar with what [Plugins](/plugins) are available and how to [write your own](/guides/writing-plugins) to support the folks who will be authoring the content. The more advanced your use case is you can explore topics as they become applicable.
## Where can I see Player how player is being used?
+
One of the easiest ways to see Player in action is through our [Storybook](https://player-ui.github.io/latest/tools/storybook). This will allow you to take a look at how some of the JSON is passed into player, and what that might look like with our set of reference assets.
-If you wanted to get started on using player, please check out our [Getting Started Guide](https://player-ui.github.io/latest/getting-started).
+If you wanted to get started on using player, please check out our [Getting Started Guide](/guides/getting-started).
## How is Player versioned?
-Player follows [semantic versioning](https://semver.org/). We will also publish changelogs for every release.
+
+Player follows [semantic versioning](https://semver.org/). We will also publish changelogs for every release.
- A _Major_ release will denote a breaking change such that it would not, without changes to your implementation or content, work as a drop in replacement. We try and avoid these and will typically batch many breaking changes into a major release to make updating more of a "all in one go" effort. Additionally we will typically announce these releases and make a RC available for users to test and proactively start updates. A migration guide will also be published with an advisory on the changes and what the recommended migration path is.
-- A _Minor_ release will denote the addition of new functionality that is backward compatible with the previous release. When a new minor version is published we highly encourage users to update promptly.
+- A _Minor_ release will denote the addition of new functionality that is backward compatible with the previous release. When a new minor version is published we highly encourage users to update promptly.
-- A _Patch_ release will denote a bugfix or a minor non-functional change.
+- A _Patch_ release will denote a bugfix or a minor non-functional change.
-## I am having issues using Player, how can I get help?
-Head over to our [issues page](https://github.com/player-ui/player/issues) on Github and feel free to open a ticket with the bug report template and we'll do our best to get back to you. The more detail you include the easier it will be for us to help troubleshoot.
+## I am having issues using Player, how can I get help?
+
+Head over to our [issues page](https://github.com/player-ui/player/issues) on Github and feel free to open a ticket with the bug report template and we'll do our best to get back to you. The more detail you include the easier it will be for us to help troubleshoot.
+
+### Contributing
-### Contributing
Check out the [Contributing Guide](https://github.com/player-ui/player/blob/main/CONTRIBUTING.md) as this will show you all of the requirements to get started using Player, how to contribute, and some platform specific guides.
-## I need Player to do _____, can we contribute back to Player?
+## I need Player to do **\_**, can we contribute back to Player?
+
We love and highly encourage open source contributions! One thing that we ask to keep in mind is that Player is supposed to be generic and flexible. We try to keep any application/implementation specific plugins and assets in a separate codebase. While **most** functionality can be added though plugins we know that sometimes changes in Player itself might be required. We are definitely open to these changes but take great effort to ensure that there are minimal breaking changes and we aren't narrowing Player's functionality.
diff --git a/docs/site/pages/team.mdx b/docs/site/src/content/docs/player/team.mdx
similarity index 85%
rename from docs/site/pages/team.mdx
rename to docs/site/src/content/docs/player/team.mdx
index 3c248564f..b0d16f25e 100644
--- a/docs/site/pages/team.mdx
+++ b/docs/site/src/content/docs/player/team.mdx
@@ -2,11 +2,12 @@
title: Player Team
---
-# The Player Team
-
## Who We Are
-The Player Team is comprised of a group of engineers at Intuit who are passionate about dynamic experiences. Our multidisciplinary background and our multi-platform experience has allowed our team to create and support the Player framework internally for the past few years. You may have seen some of the other open-source projects from out team including [auto](https://github.com/intuit/auto), [design-systems-cli](https://github.com/intuit/design-systems-cli), [hooks](https://github.com/intuit/hooks), [proof](https://github.com/intuit/proof), and more. We are excited to share our work with the open source community and see how Player grows in the years to come.
-## The Team
+The Player Team is comprised of a group of engineers at Intuit who are passionate about dynamic experiences. Our multidisciplinary background and our multi-platform experience has allowed our team to create and support the Player framework internally for the past few years. You may have seen some of the other open-source projects from out team including [auto](https://github.com/intuit/auto), [design-systems-cli](https://github.com/intuit/design-systems-cli), [hooks](https://github.com/intuit/hooks), [proof](https://github.com/intuit/proof), and more. We are excited to share our work with the open source community and see how Player grows in the years to come.
+
+## The Team
+
+import PlayerTeam from "../../../components/PlayerTeam.astro";
-
+
diff --git a/docs/site/pages/plugins/coroutines.mdx b/docs/site/src/content/docs/plugins/android/coroutines.mdx
similarity index 78%
rename from docs/site/pages/plugins/coroutines.mdx
rename to docs/site/src/content/docs/plugins/android/coroutines.mdx
index d4f5e2c9d..f3522a667 100644
--- a/docs/site/pages/plugins/coroutines.mdx
+++ b/docs/site/src/content/docs/plugins/android/coroutines.mdx
@@ -1,9 +1,8 @@
---
title: Coroutines
-platform: android
---
-# Kotlin Coroutines
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
Kotlin coroutines is a popular Kotlin library to handle asynchronous programming and concurrency in the JVM. More information on Coroutines can be found [here](https://kotlinlang.org/docs/coroutines-overview.html)
This module contains several JVM exclusive plugins to aid various tooling needs.
@@ -15,7 +14,7 @@ Plugin using a `ReceiveChannel` to provide an updated asset whenever the Player
### Usage
-
+
In build.gradle
```kotlin
@@ -23,26 +22,27 @@ implementation "com.intuit.playerui.plugins:coroutines:$PLAYER_VERSION"
```
In Player constructor
+
```kotlin
import com.intuit.playerui.plugins.coroutines.UpdatesPlugin
val plugins = listOf(UpdatesPlugin())
AndroidPlayer(plugins)
```
-
-
+
+
### API
-
+
The API for this plugin revolves around the `ReceiveChannel` for asset updates.
Public API available from sources here:
-[UpdatesPlugin](https://github.com/player-ui/player/blob/main/plugins/coroutines/jvm/src/main/kotlin/com/intuit/player/plugins/coroutines/UpdatesPlugin.kt)
+[UpdatesPlugin](https://github.com/player-ui/player/blob/main/plugins/coroutines/jvm/src/main/kotlin/com/intuit/playerui/plugins/coroutines/UpdatesPlugin.kt)
-
+
## FlowScopePlugin
@@ -53,7 +53,7 @@ All operations launched using the scope will be cancelled when player changes st
### Usage
-
+
In build.gradle
```kotlin
@@ -61,23 +61,25 @@ implementation "com.intuit.playerui.plugins:coroutines:$PLAYER_VERSION"
```
In Player constructor
+
```kotlin
import com.intuit.playerui.plugins.coroutines.FlowScopePlugin
val plugins = listOf(FlowScopePlugin())
AndroidPlayer(plugins)
```
-
-
+
+
### API
-
+
Public API available from sources here:
-[FlowScopePlugin](https://github.com/player-ui/player/blob/main/plugins/coroutines/jvm/src/main/kotlin/com/intuit/player/plugins/coroutines/FlowScopePlugin.kt)
-
-
\ No newline at end of file
+[FlowScopePlugin](https://github.com/player-ui/player/blob/main/plugins/coroutines/jvm/src/main/kotlin/com/intuit/playerui/plugins/coroutines/FlowScopePlugin.kt)
+
+
+
diff --git a/docs/site/pages/plugins/set-timeout.mdx b/docs/site/src/content/docs/plugins/android/set-timeout.mdx
similarity index 91%
rename from docs/site/pages/plugins/set-timeout.mdx
rename to docs/site/src/content/docs/plugins/android/set-timeout.mdx
index de673f465..6b010c2df 100644
--- a/docs/site/pages/plugins/set-timeout.mdx
+++ b/docs/site/src/content/docs/plugins/android/set-timeout.mdx
@@ -1,20 +1,19 @@
---
title: SetTimeout Plugin
-platform: android
---
-# setTimeout Plugin
-
The only explicit runtime plugin in the core Android plugin set, the `SetTimeoutPlugin` is a `RuntimePlugin` written to provide the global `setTimeout` method to the runtime.
-## Usage
+## Usage
In build.gradle
+
```kotlin
implementation "com.intuit.playerui.plugins:set-time-out:$PLAYER_VERSION"
```
In plugin implementation
+
```kotlin
class PluginThatNeedsSetTimeout : RuntimePlugin {
@@ -24,4 +23,4 @@ class PluginThatNeedsSetTimeout : RuntimePlugin {
}
}
-```
\ No newline at end of file
+```
diff --git a/docs/site/pages/plugins/asset-transform.mdx b/docs/site/src/content/docs/plugins/core/asset-transform.mdx
similarity index 83%
rename from docs/site/pages/plugins/asset-transform.mdx
rename to docs/site/src/content/docs/plugins/core/asset-transform.mdx
index ee4be5ed4..54376ef7b 100644
--- a/docs/site/pages/plugins/asset-transform.mdx
+++ b/docs/site/src/content/docs/plugins/core/asset-transform.mdx
@@ -1,13 +1,12 @@
---
title: Asset Transform
-platform: core,react
---
-# Asset Transform Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
## What are _transforms_?
-Transforms are functions that map the authored JSON representation of an asset into a stateful JavaScript object, including all of the properties required for that asset to interact with the data-model, navigation, and the rest of Player. This allows UI implementations to have consistent treatment and behavior. While the transform plugin is registered in the _core_ layer, it can be wrapped by the native platforms.
+Transforms are functions that map the authored JSON representation of an asset into a stateful JavaScript object, including all of the properties required for that asset to interact with the data-model, navigation, and the rest of Player. This allows UI implementations to have consistent treatment and behavior. While the transform plugin is registered in the _core_ layer, it can be wrapped by the native platforms.
## Partial Matching
@@ -15,18 +14,16 @@ The transform plugin makes use of the `partial-match-registry` which ranks match
## Usage
-
-
+
## Transform Arguments
Each `transform` is a function that is passed 3 arguments: the current `asset` node, and an _options_ object containing a data-model, expression-evaluator, binding-parser, and a flow transition function, and a store for state management. The transforms should return an immutable representation of the asset, including any means of interacting with the _player_.
-
```javascript
-import { Player } from '@player-ui/player';
-import { AssetTransformPlugin } from '@player-ui/asset-transform-plugin';
+import { Player } from "@player-ui/player";
+import { AssetTransformPlugin } from "@player-ui/asset-transform-plugin";
// Add it to Player
@@ -36,21 +33,20 @@ const player = new Player({
new Registry([
// Register a match for any _action_ type with a custom transform.
[
- { type: 'action' },
- value => {
+ { type: "action" },
+ (value) => {
return {
...value,
- hello: () => console.log('hello world')
+ hello: () => console.log("hello world"),
};
- }
- ]
- ])
- )
- ]
+ },
+ ],
+ ]),
+ ),
+ ],
});
```
-
### State Management
Often times node transforms require some state to be stored between updates. Historically this state was put in the data-model under `local` (to not send it back to the server), but updates became difficult to manage, and namespace collisions under _local_ were up to the transforms to discern.
@@ -67,18 +63,18 @@ const transform = (asset, options, store) => {
count,
increment() {
setCount(count + 1);
- }
+ },
};
};
```
-
+
## Example
-
+
If the authored JSON is:
@@ -102,14 +98,14 @@ the transform-plugin would run the transform on the `action` asset, attaching a
actions: [
{
asset: {
- id: 'foo',
- type: 'action',
- hello: () => console.log('hello world')
- }
- }
+ id: "foo",
+ type: "action",
+ hello: () => console.log("hello world"),
+ },
+ },
];
}
```
-
+
diff --git a/docs/site/pages/plugins/common-expressions.mdx b/docs/site/src/content/docs/plugins/core/common-expressions.mdx
similarity index 71%
rename from docs/site/pages/plugins/common-expressions.mdx
rename to docs/site/src/content/docs/plugins/core/common-expressions.mdx
index 17b2566e6..501bfaee8 100644
--- a/docs/site/pages/plugins/common-expressions.mdx
+++ b/docs/site/src/content/docs/plugins/core/common-expressions.mdx
@@ -1,9 +1,8 @@
---
title: Common Expressions
-platform: react,core,ios
---
-# Common Expressions Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
This plugin exposes some basic expressions into Player content.
@@ -12,7 +11,7 @@ It also serves as a good reference to adding your own custom expressions into Pl
## Usage
-
+
Install the plugin:
@@ -21,8 +20,9 @@ yarn add @player-ui/common-types-plugin
```
Add it to Player:
+
```js
-import CommonExpressionsPlugin from '@player-ui/common-expressions-plugin';
+import CommonExpressionsPlugin from "@player-ui/common-expressions-plugin";
const commonExpressionsPlugin = new CommonExpressionsPlugin();
const player = new Player({ plugins: [commonExpressionsPlugin] });
@@ -33,9 +33,9 @@ player.start(myFlow);
This will allow any included expressions or custom expressions to be used in the content
-
+
-
+
### CocoaPods
@@ -63,7 +63,8 @@ var body: some View {
)
}
```
-
+
+
@@ -76,7 +77,7 @@ var body: some View {
> Gets the size of a value. This is the number of keys in an object, the length of a string, or the number of items in an array.
```ts
-function size(value: string | array | object): number
+function size(value: string | array | object): number;
```
#### length
@@ -88,19 +89,19 @@ function size(value: string | array | object): number
> Concatenates arrays together, or strings into 1 value
```ts
-function concat(...values: Array): Array
+function concat(...values: Array): Array;
```
---
-## Strings
+## Strings
#### trim
> Trims whitespace from the leading and trailing edges of a string
```ts
-function trim(value: string): string
+function trim(value: string): string;
```
#### upperCase
@@ -108,7 +109,7 @@ function trim(value: string): string
> Transforms the string to all uppercase.
```ts
-function upperCase(value: string): string
+function upperCase(value: string): string;
```
#### lowerCase
@@ -116,7 +117,7 @@ function upperCase(value: string): string
> Transforms the string to all lowercase.
```ts
-function lowerCase(value: string): string
+function lowerCase(value: string): string;
```
#### titleCase
@@ -124,7 +125,7 @@ function lowerCase(value: string): string
> Transforms the string to title case. Each word is capitalized.
```ts
-function titleCase(value: string): string
+function titleCase(value: string): string;
```
#### sentenceCase
@@ -132,7 +133,7 @@ function titleCase(value: string): string
> Transforms the string to sentence case. The first word is capitalized.
```ts
-function sentenceCase(value: string): string
+function sentenceCase(value: string): string;
```
#### replace
@@ -140,7 +141,11 @@ function sentenceCase(value: string): string
> Replaces all instances of pattern in string with replacement. The pattern can also be a regex.
```ts
-function replace(value: string, pattern: string | RegExp, replacement: string): string
+function replace(
+ value: string,
+ pattern: string | RegExp,
+ replacement: string,
+): string;
```
#### containsAny
@@ -148,7 +153,7 @@ function replace(value: string, pattern: string | RegExp, replacement: string):
> Checks if a given string contains any keywords present in the given array.
```ts
-function containsAny(value: string, keywords: Array): boolean
+function containsAny(value: string, keywords: Array): boolean;
```
---
@@ -160,7 +165,7 @@ function containsAny(value: string, keywords: Array): boolean
> Converts the given value to a number if possible. Will handle removing currency modifiers and comma delimitated values.
```ts
-function number(value: string): number | undefined
+function number(value: string): number | undefined;
```
#### round
@@ -168,7 +173,7 @@ function number(value: string): number | undefined
> Rounds the given number to the nearest integer.
```ts
-function round(value: number): number
+function round(value: number): number;
```
#### floor
@@ -176,7 +181,7 @@ function round(value: number): number
> Rounds the number down the the nearest integer
```ts
-function floor(value: number): number
+function floor(value: number): number;
```
#### ceil
@@ -184,7 +189,7 @@ function floor(value: number): number
> Rounds the number up the the nearest integer
```ts
-function ceil(value: number): number
+function ceil(value: number): number;
```
#### sum
@@ -192,7 +197,7 @@ function ceil(value: number): number
> Sums up all arguments
```ts
-function sum(...values: Array): number
+function sum(...values: Array): number;
```
---
@@ -204,7 +209,11 @@ function sum(...values: Array): number
> Finds the index of the item in the given array (or array reference). Returns -1 for indexes that aren't found
```ts
-function findPropertyIndex(binding: Binding | Array, searchProperty: string, searchValue: any): number
+function findPropertyIndex(
+ binding: Binding | Array,
+ searchProperty: string,
+ searchValue: any,
+): number;
```
### findProperty
@@ -212,5 +221,11 @@ function findPropertyIndex(binding: Binding | Array, searchProperty: string, sea
> Finds the item in the given array that matches the search criteria. Optionally return a specific property or a fallback value if not found
```ts
-function findPropertyIndex(binding: Binding | Array, searchProperty: string, searchValue: any, fallBackProperty?: string, fallBackValue?: T): T
+function findPropertyIndex(
+ binding: Binding | Array,
+ searchProperty: string,
+ searchValue: any,
+ fallBackProperty?: string,
+ fallBackValue?: T,
+): T;
```
diff --git a/docs/site/pages/plugins/common-types.mdx b/docs/site/src/content/docs/plugins/core/common-types.mdx
similarity index 57%
rename from docs/site/pages/plugins/common-types.mdx
rename to docs/site/src/content/docs/plugins/core/common-types.mdx
index 881d7ba8b..f99bd2f9e 100644
--- a/docs/site/pages/plugins/common-types.mdx
+++ b/docs/site/src/content/docs/plugins/core/common-types.mdx
@@ -1,9 +1,8 @@
---
title: Common Types
-platform: react,core,ios
---
-# Common Types Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
This plugin exposes some basic `DataTypes`, `validations`, and `formats` into Player content.
@@ -12,7 +11,7 @@ It also serves as a good reference to adding your own custom types into Player.
## Usage
-
+
Install the plugin:
@@ -21,8 +20,9 @@ yarn add @player-ui/common-types-plugin
```
Add it to Player:
+
```js
-import CommonTypesPlugin from '@player-ui/common-types-plugin';
+import CommonTypesPlugin from "@player-ui/common-types-plugin";
const commonTypesPlugin = new CommonTypesPlugin();
const player = new Player({ plugins: [commonTypesPlugin] });
@@ -33,9 +33,9 @@ player.start(myFlow);
This will allow any `DataTypes`, `formats`, `validations` and custom data types to be used in the content
-
+
-
+
### CocoaPods
@@ -64,18 +64,16 @@ var body: some View {
}
```
-
+
-
## Formats
#### commaNumber
-
-* **format**: Formats a number (or string containing only numbers) into a comma delineated string.
-* **deformat**: Converts a comma delineated string into a number
+- **format**: Formats a number (or string containing only numbers) into a comma delineated string.
+- **deformat**: Converts a comma delineated string into a number
Options:
@@ -87,11 +85,11 @@ Options:
#### integer
-* **deformat**: converts a string containing only integers to an integer
+- **deformat**: converts a string containing only integers to an integer
#### date
-* **format**: Formats a string of numbers into a slash separated date
+- **format**: Formats a string of numbers into a slash separated date
Options:
@@ -103,8 +101,8 @@ Options:
#### currency
-* **format**: Formats a number of string into a currency value
-* **deformat**: Converts a currency value into a number
+- **format**: Formats a number of string into a currency value
+- **deformat**: Converts a currency value into a number
Options:
@@ -118,7 +116,7 @@ Options:
#### phone
-* **format**: Formats the value as a phone number
+- **format**: Formats the value as a phone number
Options:
@@ -133,9 +131,11 @@ Options:
## Validations
#### required
+
> Asserts that a value is not `null`, `undefined`, or an empty string
-Options:
+Options:
+
```ts
{
/** An expression to limit the assertion only if the expression evaluates to truthy **/
@@ -146,13 +146,14 @@ Options:
}
```
-**Constants Support**:
+**Constants Support**:
-* namespace: `constants`
-* path: `validation.required`
-* message: "A value is required"
+- namespace: `constants`
+- path: `validation.required`
+- message: "A value is required"
#### expression
+
> Uses an expression to evaluate the validation assertion
Options:
@@ -164,77 +165,80 @@ Options:
}
```
-**Constants Support**:
-
-* namespace: `constants`
-* path: `validation.expression`
-* message: "Expression evaluation failed"
+**Constants Support**:
+- namespace: `constants`
+- path: `validation.expression`
+- message: "Expression evaluation failed"
#### readonly
+
> Asserts that the value cannot change
-**Constants Support**:
+**Constants Support**:
-* namespace: `constants`
-* path: `validation.readonly`
-* message: "Value cannot be modified"
+- namespace: `constants`
+- path: `validation.readonly`
+- message: "Value cannot be modified"
#### string
+
> Asserts that the value is a string
-**Constants Support**:
+**Constants Support**:
-* namespace: `constants`
-* path: `validation.string`
-* message: "Value must be a string"
-* parameters:
+- namespace: `constants`
+- path: `validation.string`
+- message: "Value must be a string"
+- parameters:
- `type`: the type of value being validated
-
#### integer
+
> Asserts that the value is an integer
-**Constants Support**:
+**Constants Support**:
-* namespace: `constants`
-* path: `validation.integer`
-* message: "Value must be an integer"
-* parameters:
+- namespace: `constants`
+- path: `validation.integer`
+- message: "Value must be an integer"
+- parameters:
- `type`: the type of value being validated
- `flooredValue`: the floored value of the value being validated
-
#### collection
+
> Asserts that the value is an array
-**Constants Support**:
+**Constants Support**:
-* namespace: `constants`
-* path: `validation.collection`
-* message: "Cannot set collection to non-array"
+- namespace: `constants`
+- path: `validation.collection`
+- message: "Cannot set collection to non-array"
#### oneOf
+
> Asserts that the value is one of the pre-defined accepted values
-Options:
+Options:
+
```ts
{
options?: Array;
}
```
-**Constants Support**:
-
-* namespace: `constants`
-* path: `validation.oneof`
-* message: "Cannot set collection to non-array"
+**Constants Support**:
+- namespace: `constants`
+- path: `validation.oneof`
+- message: "Cannot set collection to non-array"
#### regex
+
> Asserts that the value matches the provided regular expression
-Options:
+Options:
```ts
{
@@ -242,16 +246,17 @@ Options:
}
```
-**Constants Support**:
-
-* namespace: `constants`
-* path: `validation.regex`
+**Constants Support**:
+- namespace: `constants`
+- path: `validation.regex`
#### length
+
> Asserts that the value matches the given length criteria. Uses character counts for strings, and key-length for objects, and array length for arrays.
Options:
+
```ts
{
min?: number;
@@ -260,115 +265,125 @@ Options:
}
```
-**Constants Support**:
+**Constants Support**:
-* namespace: `constants`
-* path: `validation.minimum`, `validation.maximum`
-* message: "At least ${min} items needed", "Up to ${max} items allowed"
-* parameters:
+- namespace: `constants`
+- path: `validation.minimum`, `validation.maximum`
+- message: "At least \$\{min\} items needed", "Up to \$\{max\} items allowed"
+- parameters:
- `validationLength`: Returns the length of the value being validated
-
-
#### min
+
> Assets that the numeric value is at least as large as the target
Options:
+
```ts
{
value: number;
}
```
-**Constants Support**:
+**Constants Support**:
-* namespace: `constants`
-* path: `validation.min`
-* message: "Must be at least ${value}"
+- namespace: `constants`
+- path: `validation.min`
+- message: "Must be at least \$\{value\}"
#### max
+
> Assets that the numeric value is at no larger the target
Options:
+
```ts
{
value: number;
}
```
-**Constants Support**:
+**Constants Support**:
-* namespace: `constants`
-* path: `validation.max`
-* message: "Cannot exceed ${value}"
+- namespace: `constants`
+- path: `validation.max`
+- message: "Cannot exceed \$\{value\}"
#### email
-> Asserts that the value follows an email pattern
-**Constants Support**:
+> Asserts that the value follows an email pattern
-* namespace: `constants`
-* path: `validation.email`
-* message: "Improper email format"
+**Constants Support**:
+- namespace: `constants`
+- path: `validation.email`
+- message: "Improper email format"
#### phone
+
> Asserts that the value follows an phone number pattern
-**Constants Support**:
+**Constants Support**:
-* namespace: `constants`
-* path: `validation.phone`
-* message: "Invalid phone number"
+- namespace: `constants`
+- path: `validation.phone`
+- message: "Invalid phone number"
#### zip
-> Asserts that the value follows an zip-code pattern
-**Constants Support**:
+> Asserts that the value follows an zip-code pattern
-* namespace: `constants`
-* path: `validation.zip`
-* message: "Invalid zip code"
+**Constants Support**:
+- namespace: `constants`
+- path: `validation.zip`
+- message: "Invalid zip code"
---
## Data Types
#### BooleanType
+
> A true or false value.
-* **validations**: `oneOf([true, false])`
+- **validations**: `oneOf([true, false])`
#### IntegerType
+
> An integer value
-* **validations**: `integer`
-* **format**: `integer`
+- **validations**: `integer`
+- **format**: `integer`
#### IntegerPosType
+
> An integer value greater than 0
-* **validations**: `integer`, `min(1)`
-* **format**: `integer`
+- **validations**: `integer`, `min(1)`
+- **format**: `integer`
#### StringType
+
> A string value
-* **validations**: `string`
+- **validations**: `string`
#### CollectionType
+
> An array of items
-* **validations**: `collection`
+- **validations**: `collection`
#### DateType
+
> A value representing a date
-* **format**: `date`
+- **format**: `date`
#### PhoneType
+
> A value representing a phone number
-* **validations**: `phone`
-* **format**: `phone` (`(###) ###-####`)
+- **validations**: `phone`
+- **format**: `phone` (`(###) ###-####`)
diff --git a/docs/site/pages/plugins/computed-properties.mdx b/docs/site/src/content/docs/plugins/core/computed-properties.mdx
similarity index 82%
rename from docs/site/pages/plugins/computed-properties.mdx
rename to docs/site/src/content/docs/plugins/core/computed-properties.mdx
index 709887501..850a4bfe4 100644
--- a/docs/site/pages/plugins/computed-properties.mdx
+++ b/docs/site/src/content/docs/plugins/core/computed-properties.mdx
@@ -1,32 +1,31 @@
---
title: Computed Properties
-platform: react,core
---
-# Computed Properties Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
-This plugin allows users to specify a path in the data-model (binding) as a computed property in the schema.
+This plugin allows users to specify a path in the data-model (binding) as a computed property in the schema.
Anytime this binding is read from, the given expression will be evaluated and returned instead of the it being read from the actual model. Writes to the binding will be prevented, and an error will be thrown.
## Usage
-
+
Add the plugin to Player:
```js
-import { Player } from '@player-ui/player';
-import { ComputedPropertiesPlugin } from '@player-ui/computed-properties-plugin';
+import { Player } from "@player-ui/player";
+import { ComputedPropertiesPlugin } from "@player-ui/computed-properties-plugin";
const player = new Player({
plugins: [new ComputedPropertiesPlugin()],
});
```
-
+
-
+
### CocoaPods
@@ -51,12 +50,13 @@ var body: some View {
)
}
```
-
+
+
## Expression Data Type
-The computed properties plugin introspects the schema, looking for any `DataType` that uses the `Expression`:
+The computed properties plugin introspects the schema, looking for any `DataType` that uses the `Expression`:
```json
{
diff --git a/docs/site/pages/plugins/data-change-listener.mdx b/docs/site/src/content/docs/plugins/core/data-change-listener.mdx
similarity index 89%
rename from docs/site/pages/plugins/data-change-listener.mdx
rename to docs/site/src/content/docs/plugins/core/data-change-listener.mdx
index bca06544b..d27ae87e8 100644
--- a/docs/site/pages/plugins/data-change-listener.mdx
+++ b/docs/site/src/content/docs/plugins/core/data-change-listener.mdx
@@ -1,9 +1,8 @@
---
title: Data Change Listener
-platform: react,core
---
-# Data Change Listener Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
This plugin enables users to subscribe to data-change events within a view, and run expressions when the target value changes. Expressions are added to a listeners property of the view, with events prefixed by `dataChange` and the target binding:
@@ -21,20 +20,20 @@ This plugin enables users to subscribe to data-change events within a view, and
## Installation
-
+
Add it to Player:
```js
-import { Player } from '@player-ui/player';
-import { DataChangePlugin } from '@player-ui/data-change-plugin';
+import { Player } from "@player-ui/player";
+import { DataChangePlugin } from "@player-ui/data-change-plugin";
const player = new Player({
- plugins: [new DataChangePlugin()]
+ plugins: [new DataChangePlugin()],
});
```
-
+
## Usage
diff --git a/docs/site/pages/plugins/data-filter.mdx b/docs/site/src/content/docs/plugins/core/data-filter.mdx
similarity index 62%
rename from docs/site/pages/plugins/data-filter.mdx
rename to docs/site/src/content/docs/plugins/core/data-filter.mdx
index ec386875c..9c981af3e 100644
--- a/docs/site/pages/plugins/data-filter.mdx
+++ b/docs/site/src/content/docs/plugins/core/data-filter.mdx
@@ -1,27 +1,26 @@
---
title: Data Filter
-platform: react,core
---
-# Data Filter Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
The `data-filter-plugin` enables users to filter out segments of the data-model during serialization.
## Usage
-
+
Add the plugin to Player and configure the exclusion paths:
```ts
-import { Player } from '@player-ui/player';
-import { DataFilterPlugin } from '@player-ui/data-filter-plugin';
+import { Player } from "@player-ui/player";
+import { DataFilterPlugin } from "@player-ui/data-filter-plugin";
const player = new Player({
plugins: [
new DataFilterPlugin({
- paths: ['local', 'constants'],
+ paths: ["local", "constants"],
}),
],
});
@@ -29,5 +28,5 @@ const player = new Player({
This will exclude any top-level `local` or `constants` paths in the data-model from appearing in the serialized response.
-
-
\ No newline at end of file
+
+
diff --git a/docs/site/pages/plugins/expression.mdx b/docs/site/src/content/docs/plugins/core/expression.mdx
similarity index 81%
rename from docs/site/pages/plugins/expression.mdx
rename to docs/site/src/content/docs/plugins/core/expression.mdx
index c10b89f20..d940b4b3f 100644
--- a/docs/site/pages/plugins/expression.mdx
+++ b/docs/site/src/content/docs/plugins/core/expression.mdx
@@ -1,40 +1,40 @@
---
title: Expression
-platform: react,core,ios,android
---
-# Expression Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
This plugin assists with exposing custom expressions to Player content.
## Usage
-
+
Define handlers for the expressions you wish to add:
```ts
-import { ExpressionHandler, ExpressionContext } from '@player-ui/expression-plugin';
+import {
+ ExpressionHandler,
+ ExpressionContext,
+} from "@player-ui/expression-plugin";
const customExpressionHandler: ExpressionHandler = (ctx: ExpressionContext) => {
- return 'Hello World!'
-}
+ return "Hello World!";
+};
```
Register with Player. Subsequent registrations of an expression with the same name will override previous values.
```ts
-import { Player } from '@player-ui/player';
-import { ExpressionPlugin } from '@player-ui/expression-plugin';
+import { Player } from "@player-ui/player";
+import { ExpressionPlugin } from "@player-ui/expression-plugin";
const player = new Player({
plugins: [
- new ExpressionPlugin([
- ['myCustomFunction', customExpressionHandler]
- ])
- ]
-})
+ new ExpressionPlugin([["myCustomFunction", customExpressionHandler]]),
+ ],
+});
```
Any calls to `myCustomFunction()` within the flow will utilize the newly registered expression:
@@ -49,10 +49,11 @@ Any calls to `myCustomFunction()` within the flow will utilize the newly registe
}
```
-
-
+
+
### CocoaPods
+
Add the subspec to your `Podfile`
```ruby
@@ -78,6 +79,7 @@ let expressionPlugin = ExpressionPlugin(expressions: [
}
])
```
+
#### Arguments
Arguments can be passed to custom expressions, and your handler receives the arguments as an array of Any:
@@ -99,18 +101,21 @@ let expressionPlugin = ExpressionPlugin(expressions: [
])
```
-
-
+
+
The `ExpressionPlugin` enables consumers to register custom expressions in native JVM code. Simply supply a map of expression name to handler on instantiation, and the expressions will be available within the content. Handlers receive arguments are as a `List` and are permitted to return `Any?`.
## Usage
+
In build.gradle
+
```kotlin
implementation "com.intuit.playerui.plugins:expression:$PLAYER_VERSION"
```
In Player constructor
+
```kotlin
import com.intuit.playerui.plugins.expression.ExpressionPlugin
@@ -126,6 +131,7 @@ AndroidPlayer(expressionPlugin)
```
In Player content
+
```json
{
"id": "hello-world-text",
@@ -134,5 +140,5 @@ In Player content
}
```
-
-
\ No newline at end of file
+
+
diff --git a/docs/site/pages/plugins/markdown.mdx b/docs/site/src/content/docs/plugins/core/markdown.mdx
similarity index 73%
rename from docs/site/pages/plugins/markdown.mdx
rename to docs/site/src/content/docs/plugins/core/markdown.mdx
index 9ef462fff..650800c84 100644
--- a/docs/site/pages/plugins/markdown.mdx
+++ b/docs/site/src/content/docs/plugins/core/markdown.mdx
@@ -1,31 +1,30 @@
---
title: Markdown
-platform: core
---
-# Markdown Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
The `markdown-plugin` adds support for parsing markdown content to Player Assets. This plugin is asset set agnostic, so it expects a mappers record to inform how to transform markdown content into valid Player Content with support from your asset set.
## Usage
-
+
### Defining The Mappers
```ts
-import type { Mappers } from '@player-ui/markdown-plugin';
+import type { Mappers } from "@player-ui/markdown-plugin";
export const mappers: Mappers = {
text: ({ originalAsset, value }) => ({
id: `${originalAsset.id}-text`,
- type: 'text',
+ type: "text",
value,
}),
image: ({ originalAsset, value, src }) => ({
id: `${originalAsset.id}-image`,
- type: 'image',
+ type: "image",
accessibility: value,
metaData: {
ref: src,
@@ -38,8 +37,8 @@ export const mappers: Mappers = {
## Add the plugin to Player
```ts
-import { MarkdownPlugin } from '@player-ui/markdown-plugin';
-import mappers from './mappers';
+import { MarkdownPlugin } from "@player-ui/markdown-plugin";
+import mappers from "./mappers";
const markdownPlugin = new MarkdownPlugin(myMarkdownMappers);
// Add it to the player
@@ -47,6 +46,6 @@ const player = new Player({
plugins: [markdownPlugin],
});
```
-
-
+
+
diff --git a/docs/site/pages/plugins/meta.mdx b/docs/site/src/content/docs/plugins/core/meta.mdx
similarity index 63%
rename from docs/site/pages/plugins/meta.mdx
rename to docs/site/src/content/docs/plugins/core/meta.mdx
index 83437a3d1..36759d044 100644
--- a/docs/site/pages/plugins/meta.mdx
+++ b/docs/site/src/content/docs/plugins/core/meta.mdx
@@ -3,30 +3,27 @@ title: Meta
platform: core
---
-# Meta Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
The Meta Plugin is an easy way to combine multiple _other_ plugins into 1 group. It is often used when sharing a set of plugins across platforms (each platform registering 1 common set of _core_ plugins).
-# Usage
+## Usage
-
+
Create a grouping of other plugins:
```js
-import { MetaPlugin } from '@player-ui/meta-plugin';
+import { MetaPlugin } from "@player-ui/meta-plugin";
-const pluginGroup = new MetaPlugin([
- new Plugin1(),
- new Plugin2()
-]);
+const pluginGroup = new MetaPlugin([new Plugin1(), new Plugin2()]);
```
Add the plugin to Player:
```js
-import { Player } from '@player-ui/player';
+import { Player } from "@player-ui/player";
const player = new Player({
plugins: [pluginGroup],
@@ -35,5 +32,5 @@ const player = new Player({
You can share `pluginGroup` with others as an easy way to group multiple plugin features together.
-
-
\ No newline at end of file
+
+
diff --git a/docs/site/pages/plugins/stage-revert-data.mdx b/docs/site/src/content/docs/plugins/core/stage-revert-data.mdx
similarity index 87%
rename from docs/site/pages/plugins/stage-revert-data.mdx
rename to docs/site/src/content/docs/plugins/core/stage-revert-data.mdx
index 1b02ee8cc..f6a7bc6f4 100644
--- a/docs/site/pages/plugins/stage-revert-data.mdx
+++ b/docs/site/src/content/docs/plugins/core/stage-revert-data.mdx
@@ -1,9 +1,9 @@
---
title: Stage Revert Data
-platform: core,ios
+platform: core
---
-# Stage Revert Data Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
This plugin enables users to temporarily stage data changes before committing to the actual data model
@@ -31,22 +31,23 @@ It also should include a list of acceptable `commitTransitions` valid `VIEW` nam
## Example
-
+
Simply add the plugin to the config when constructing a player instance.
```javascript
-import StageRevertPlugin from '@player/stage-revert-data';
+import StageRevertPlugin from "@player/stage-revert-data";
const player = new Player({
plugins: [new StageRevertPlugin()],
});
```
-
-
+
+
### CocoaPods
+
Add the subspec to your `Podfile`
```ruby
@@ -54,7 +55,9 @@ pod 'PlayerUI/StageRevertDataPlugin'
```
### Swift Usage
+
This plugin takes no parameters, and the configuration comes from content, it can just be added to the plugin array:
+
```swift
var body: some View {
SwiftUIPlayer(
@@ -66,5 +69,6 @@ var body: some View {
)
}
```
-
-
\ No newline at end of file
+
+
+
diff --git a/docs/site/pages/plugins/types-provider.mdx b/docs/site/src/content/docs/plugins/core/types-provider.mdx
similarity index 79%
rename from docs/site/pages/plugins/types-provider.mdx
rename to docs/site/src/content/docs/plugins/core/types-provider.mdx
index 809dc613e..d3da542d0 100644
--- a/docs/site/pages/plugins/types-provider.mdx
+++ b/docs/site/src/content/docs/plugins/core/types-provider.mdx
@@ -1,61 +1,58 @@
---
title: Types Provider
-platform: core,ios
---
-# Types Provider Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
-Similar to the [Expression Plugin](./expression), this plugin adds support for easily exposing new `DataTypes`, `formats`, and `validations` to Player's content.
+Similar to the [Expression Plugin](/plugins/core/expression), this plugin adds support for easily exposing new `DataTypes`, `formats`, and `validations` to Player's content.
## Example
-
+
Define a new validation type:
```ts
-import { ValidatorFunction } from '@player-ui/player';
+import { ValidatorFunction } from "@player-ui/player";
const customValidator: ValidatorFunction = (context, value) => {
- if (value === 'bad-value') {
+ if (value === "bad-value") {
return {
- message: "This is a bad value."
- }
+ message: "This is a bad value.",
+ };
}
-}
+};
```
-Create a new `DataType` that references it:
+Create a new `DataType` that references it:
```ts
-import { Schema } from '@player-ui/player';
+import { Schema } from "@player-ui/player";
const CustomDataType: Schema.DataType = {
- name: 'CustomType',
+ name: "CustomType",
validation: [
{
- type: "custom-validator"
- }
- ]
-}
+ type: "custom-validator",
+ },
+ ],
+};
```
Register it with Player:
```ts
-import { Player } from '@player-ui/player';
-import { TypesProviderPlugin } from '@player-ui/types-provider-plugin';
+import { Player } from "@player-ui/player";
+import { TypesProviderPlugin } from "@player-ui/types-provider-plugin";
const player = new Player({
plugins: [
new TypesProviderPlugin({
types: [CustomDataType],
- validations: [
- ['custom-validator', customValidator]
- ]
- })
- ]
+ validations: [["custom-validator", customValidator]],
+ }),
+ ],
});
```
@@ -73,12 +70,13 @@ Given a data-type reference to `CustomType` in the content, your new validation
}
```
-
-
+
+
The swift `TypesProviderPlugin` enables adding custom data types, formatters and validation purely through swift code. While in general, the recommendation would be to share a single JavaScript implementation to multiple platforms, some use cases may need a native integration.
### CocoaPods
+
Add the subspec to your `Podfile`
```ruby
@@ -127,7 +125,7 @@ let formatFunction = {value, options in
if let stringValue = value as? String {
return stringValue.replacingOccurrences(of: ".", with: ",") // Turn all periods into commas
} else {
- return value
+ return value
}
}
@@ -171,14 +169,14 @@ let formatFunction = {value, options in
return stringValue.replacingOccurrences(of: ".", with: char)
// Turn all periods into the specified character
} else {
- return value
+ return value
}
}
```
#### Custom Types
-Just as you can define custom formats and validation, you can define a custom type that encapsulates that functionality into a type, to avoid the need to keep specifying options, this is how the [common-types](./plugins/common-types) are defined, so when you choose a type like `DateType` the formatting is already set up.
+Just as you can define custom formats and validation, you can define a custom type that encapsulates that functionality into a type, to avoid the need to keep specifying options, this is how the [common-types](/plugins/core/common-types) are defined, so when you choose a type like `DateType` the formatting is already set up.
```swift
let type = CustomType(
@@ -219,5 +217,5 @@ let type = CustomType(
)
```
-
-
\ No newline at end of file
+
+
diff --git a/docs/site/pages/plugins/external-action-view-modifier.mdx b/docs/site/src/content/docs/plugins/iOS/external-action-view-modifier.mdx
similarity index 96%
rename from docs/site/pages/plugins/external-action-view-modifier.mdx
rename to docs/site/src/content/docs/plugins/iOS/external-action-view-modifier.mdx
index 4c1240656..30b083106 100644
--- a/docs/site/pages/plugins/external-action-view-modifier.mdx
+++ b/docs/site/src/content/docs/plugins/iOS/external-action-view-modifier.mdx
@@ -1,13 +1,12 @@
---
-title: External Action View Modifier
+title: External Action View Modifier
platform: ios
---
-# External Action View Modifier Plugin
-
This plugin is used to handle EXTERNAL states, allowing you to asynchronously tell Player when, and what to transition with once you have finished processing the external state request.
### CocoaPods
+
Add the subspec to your `Podfile`
```ruby
@@ -96,4 +95,4 @@ struct ExternalAlertModifier: ExternalStateViewModifier {
}
}
}
-```
\ No newline at end of file
+```
diff --git a/docs/site/pages/plugins/swiftui-pending-transaction.mdx b/docs/site/src/content/docs/plugins/iOS/swiftui-pending-transaction.mdx
similarity index 89%
rename from docs/site/pages/plugins/swiftui-pending-transaction.mdx
rename to docs/site/src/content/docs/plugins/iOS/swiftui-pending-transaction.mdx
index cceb54f61..7abbdd43a 100644
--- a/docs/site/pages/plugins/swiftui-pending-transaction.mdx
+++ b/docs/site/src/content/docs/plugins/iOS/swiftui-pending-transaction.mdx
@@ -3,11 +3,10 @@ title: SwiftUIPendingTransactionPlugin
platform: ios
---
-# SwiftUIPendingTransactionPlugin
-
The `SwiftUIPendingTransactionPlugin` allows you to register pending transactions (callbacks) in the userInfo on the decoder. Users can decide when to register, commit and clear transactions based on the use case. Anytime there is a scenario where we want a native transaction to happen while a view update is taking place, we can make use of this plugin. Below is an example used in the sample app where we can see this take place:
### CocoaPods
+
Add the subspec to your `Podfile`
```ruby
@@ -29,7 +28,6 @@ Declare a new object for keeping track of the namespaces or use the default stru
If you use the default `PendingTransactionPhases` the plugin can be defined like `SwiftUIPendingTransactionPlugin()` or using the typealias `PendingTransactionPhasesPlugin()`
Otherwise pass the new object in the generics on plugin initialization
-
**Step 2:**
If you use the default `PendingTransactionPhases`:
@@ -82,7 +80,7 @@ public extension EnvironmentValues {
To start registering transactions with the assets, access the transactionContext through the default environment variable above or the new one you created
-Register the transaction with the "input" phase (the view update) when a user starts editing the input, (code snippet taken from [InputAsset](https://github.com/player-ui/player/blob/main/ios/packages/reference-assets/Sources/SwiftUI/InputAsset.swift)
+Register the transaction with the "input" phase (the view update) when a user starts editing the input, (code snippet taken from [InputAsset](https://github.com/player-ui/player/blob/main/plugins/reference-assets/swiftui/Sources/SwiftUI/InputAsset.swift)
```swift
onEditingChanged: { editing in
@@ -100,14 +98,14 @@ onEditingChanged: { editing in
}
```
-Note: we can register multiple transactions under a single phase and we commit based on phase, when commiting a phase if multiple transactions exist they commit in no particular order
+Note: we can register multiple transactions under a single phase and we commit based on phase, when commiting a phase if multiple transactions exist they commit in no particular order
**Step 4:**
Commit the transaction (view update) before the action to navigate takes place. The WrappedFunction provides access to the userInfo where the TransactionContext is stored and users can use this how they see fit.
-Now in the [ActionAsset](https://github.com/player-ui/player/blob/main/ios/packages/reference-assets/Sources/SwiftUI/ActionAsset.swift) instead of calling WrappedFunction `run` directly, we can extend the WrappedFunction and create another function called commitCallbacksThenCall which does the same thing as the normal call function except it will check for any input callbacks and commit then if they exist.
+Now in the [ActionAsset](https://github.com/player-ui/player/blob/main/plugins/reference-assets/swiftui/Sources/SwiftUI/ActionAsset.swift) instead of calling WrappedFunction `run` directly, we can extend the WrappedFunction and create another function called commitCallbacksThenCall which does the same thing as the normal call function except it will check for any input callbacks and commit then if they exist.
```swift
extension WrappedFunction {
@@ -123,6 +121,7 @@ extension WrappedFunction {
```
Calling the new function inside of the action handler:
+
```swift
model.data.run?.commitCallbacksThenCall()
```
diff --git a/docs/site/pages/plugins/transition.mdx b/docs/site/src/content/docs/plugins/iOS/transition.mdx
similarity index 97%
rename from docs/site/pages/plugins/transition.mdx
rename to docs/site/src/content/docs/plugins/iOS/transition.mdx
index c7c26a38b..3173c214c 100644
--- a/docs/site/pages/plugins/transition.mdx
+++ b/docs/site/src/content/docs/plugins/iOS/transition.mdx
@@ -1,13 +1,11 @@
---
title: Transition Plugin
-platform: ios
---
-# Transition Plugin
-
The `TransitionPlugin` allows for specifying transitions for when Player loads a flow, and for transition between views in the same flow.
### CocoaPods
+
Add the subspec to your `Podfile`
```ruby
@@ -15,6 +13,7 @@ pod 'PlayerUI/TransitionPlugin'
```
### Swift Usage
+
```swift
SwiftUIPlayer(flow: flowString, plugins: [TransitionPlugin(popTransition: .pop)], result: $resultBinding)
```
@@ -54,4 +53,4 @@ PlayerViewTransition.push
/// Transition that slides views in from the leading edge and out from to the trailing edge of the screen
PlayerViewTransition.pop
-```
\ No newline at end of file
+```
diff --git a/docs/site/src/content/docs/plugins/index.mdx b/docs/site/src/content/docs/plugins/index.mdx
new file mode 100644
index 000000000..be2c1bd2b
--- /dev/null
+++ b/docs/site/src/content/docs/plugins/index.mdx
@@ -0,0 +1,13 @@
+---
+title: Plugins
+---
+
+import Image from "../../../components/Image.astro";
+import pluginsOverview from "../../../assets/plugin_overview.png";
+
+Plugins are one of the main ways to customize Player to suite individual use-cases.
+Internally they allow access to many of the core sub-systems, which can add features, configuration, or custom behaviors.
+
+
+
+The scope of what a plugin is capable of is pretty broad, but are typically broken down into smaller reusable modules. Some are more end-user focused ([Common Expression Plugin](/plugins/core/common-expressions) and [Common Types Plugin](/plugins/core/common-types)) while others are more relavant for other plugin developers ([Expression Plugin](/plugins/core/expression) and [Types Provider Plugin](/plugins/core/types-provider))
diff --git a/docs/site/pages/plugins/asset-provider.mdx b/docs/site/src/content/docs/plugins/multiplatform/asset-provider.mdx
similarity index 57%
rename from docs/site/pages/plugins/asset-provider.mdx
rename to docs/site/src/content/docs/plugins/multiplatform/asset-provider.mdx
index 67b610174..7f712be50 100644
--- a/docs/site/pages/plugins/asset-provider.mdx
+++ b/docs/site/src/content/docs/plugins/multiplatform/asset-provider.mdx
@@ -1,17 +1,18 @@
---
title: Asset Provider Plugin
-platform: react
---
-# Asset Provider
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
+import ContentTabs from "../../../../components/ContentTabs.astro";
-The Asset Provider Plugin enables users to easily register UI components to render their assets. It's used internally by the [Reference Assets](../assets/reference). The matches follow the same rules as asset transforms (more specific matches take priority).
+The Asset Provider Plugin enables users to easily register UI components to render their assets. It's used internally by the [Reference Assets](/assets/reference). The matches follow the same rules as asset transforms (more specific matches take priority).
-## Usage
+## Usage
### Platform
+
-
+
Install the plugin:
@@ -19,25 +20,26 @@ Install the plugin:
yarn add @player-ui/asset-provider-plugin-react
```
-Create an instance, and add it to your Player instance.
+Create an instance, and add it to your Player instance.
The API is similar to the JavaScript `Map`, and takes a list of `[match, Component]` tuples.
```tsx
-import { ReactPlayer } from '@player-ui/react';
-import { AssetProviderPlugin } from '@player-ui/asset-provider-plugin-react';
+import { ReactPlayer } from "@player-ui/react";
+import { AssetProviderPlugin } from "@player-ui/asset-provider-plugin-react";
const player = new ReactPlayer({
plugins: [
new AssetProviderPlugin([
- ['custom-asset', () =>
Hello World!
],
- [{ type: 'custom', key: 'asset' }, () =>
Other Custom Asset
],
- ])
- ]
-})
+ ["custom-asset", () =>
Hello World!
],
+ [{ type: "custom", key: "asset" }, () =>
Other Custom Asset
],
+ ]),
+ ],
+});
```
- This will register a match on `{ type: 'custom-asset' }` and `{ type: 'custom', key: 'asset' }` in the view to use your React components.
-
+This will register a match on `{ type: 'custom-asset' }` and `{ type: 'custom', key: 'asset' }` in the view to use your React components.
+
+
### Content
@@ -45,21 +47,21 @@ const player = new ReactPlayer({
In this example, when your content has assets of type `custom-asset` and `custom`, they will render `
Hello World!
` and `
Other Custom Asset
`.
-
+
```tsx
-import { Custom, CustomAsset, Collection } from 'my-assets';
+import { Custom, CustomAsset, Collection } from "my-assets";
const view = (
-
-
+
+
);
```
-
-
+
+
```json
{
@@ -79,13 +81,13 @@ const view = (
{
"asset": {
"id": "custom-1",
- "type": "custom-asset",
+ "type": "custom-asset"
}
},
{
"asset": {
"id": "custom-2",
- "type": "custom",
+ "type": "custom"
}
}
]
@@ -111,9 +113,8 @@ const view = (
}
```
- This will register a match on `{ type: 'custom-asset' }` and `{ type: 'custom', key: 'asset' }` in the view to use your React components.
-
-
+This will register a match on `{ type: 'custom-asset' }` and `{ type: 'custom', key: 'asset' }` in the view to use your React components.
+
+
-
diff --git a/docs/site/pages/plugins/async-node.mdx b/docs/site/src/content/docs/plugins/multiplatform/async-node.mdx
similarity index 92%
rename from docs/site/pages/plugins/async-node.mdx
rename to docs/site/src/content/docs/plugins/multiplatform/async-node.mdx
index f7a3f3b28..63d30fb64 100644
--- a/docs/site/pages/plugins/async-node.mdx
+++ b/docs/site/src/content/docs/plugins/multiplatform/async-node.mdx
@@ -1,11 +1,10 @@
---
title: AsyncNode Plugin
-platform: core,react,ios,android
---
-# Async Node Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
-The AsyncNode Plugin is used to enable streaming additional content into a flow that has already been loaded and rendered.
+The AsyncNode Plugin is used to enable streaming additional content into a flow that has already been loaded and rendered.
A common use case for this plugin is conversational UI, as the users input more dialogue, new content must be streamed into Player in order to keep the UI up to date.
The pillar that makes this possible is the concept of an `AsyncNode`. An `AsyncNode` is any tree node with the property `async: true`, it represents a placeholder node that will be replaced by a concrete node in the future.
@@ -38,7 +37,7 @@ Returning a value in the above context enables uses cases where the async node o
### Continuous Streaming
-In order to keep streaming in new content, there must be at least 1 or more `AsyncNode`s in the view tree at all times.
+In order to keep streaming in new content, there must be at least 1 or more `AsyncNode`s in the view tree at all times.
This means there must be a constant renewal of new `AsyncNode`s after the previous ones are resolved by the user.
## Usage
@@ -47,7 +46,7 @@ The `AsyncNodePlugin` itself accepts an options object with a `plugins` array, e
The `AsyncNodePluginPlugin` is provided as a default way of handling asset-async nodes, it is just one handler for one possible way of using async nodes. If the default behavior does not align with the desired usage, users are able to provide their own implementation of the handler in the form of a plugin to be passed to the base `AsyncNodePlugin`. The `AsyncNodePluginPlugin` also comes from the `'@player-ui/async-node-plugin'` and contains the resolver and parser functionality.
-
+
Add the plugin to Player:
@@ -83,28 +82,30 @@ const player = new Player({
]
})
```
-
-
+
+
+
The `react` version of the AsyncNodePlugin is identical to using the core plugin. Refer to core usage for handler configuration:
```js
-import { ReactPlayer } from '@player-ui/react';
-import { AsyncNodePlugin, AsyncNodePluginPlugin } from '@player-ui/async-node-plugin';
+import { ReactPlayer } from "@player-ui/react";
+import {
+ AsyncNodePlugin,
+ AsyncNodePluginPlugin,
+} from "@player-ui/async-node-plugin";
const asyncNodePlugin = new AsyncNodePlugin({
- plugins: [new AsyncNodePluginPlugin()],
+ plugins: [new AsyncNodePluginPlugin()],
});
const player = new ReactPlayer({
- plugins: [
- asyncNodePlugin
- ]
-})
+ plugins: [asyncNodePlugin],
+});
```
-
-
+
+
### CocoaPods
@@ -180,15 +181,17 @@ Note: the AsyncNode struct is already defined in the plugin with the `async` pro
As a convenience to the user, the AsyncNodePlugin just takes a callback which has the content to be returned, this is provided to the plugin which calls the the `onAsyncNode` hook tap method. The return could be a single asset node or an array of asset nodes, or null if the async node is no longer relevant.
-
-
+
+
In build.gradle
+
```kotlin
implementation "com.intuit.playerui.plugins:async-node:$PLAYER_VERSION"
```
In integration code
+
```kotlin
import com.intuit.playerui.plugins.asyncnode.AsyncNodePlugin
@@ -212,5 +215,6 @@ asyncNodePlugin.hooks.onAsyncNode.tap("handleAsync") { hookContext, node ->
AndroidPlayer(asyncNodePlugin)
```
-
+
+
diff --git a/docs/site/pages/plugins/beacon.mdx b/docs/site/src/content/docs/plugins/multiplatform/beacon.mdx
similarity index 85%
rename from docs/site/pages/plugins/beacon.mdx
rename to docs/site/src/content/docs/plugins/multiplatform/beacon.mdx
index fb1d39a24..fa57ef440 100644
--- a/docs/site/pages/plugins/beacon.mdx
+++ b/docs/site/src/content/docs/plugins/multiplatform/beacon.mdx
@@ -1,11 +1,10 @@
---
title: Beacon Plugin
-platform: core,react,ios,android
---
-# Beacon Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
-The beacon plugin enables users to send and/or collect beaconing information from assets in a normalized API. It exposes a common API for publishing beacons from an asset library, and will automatically attach itself to the current view, enabling additional meta-data to be added to each event.
+The beacon plugin enables users to send and/or collect beaconing information from assets in a normalized API. It exposes a common API for publishing beacons from an asset library, and will automatically attach itself to the current view, enabling additional meta-data to be added to each event.
## Consuming Beacons
@@ -16,7 +15,7 @@ By default, the beacon plugin returns beacons in the following format:
```ts
interface DefaultBeacon {
/** The user action taken ('clicked', 'visited') **/
- action: string;
+ action: string;
/** The type of UI element interacted with ('button', 'menu') **/
element: string;
@@ -35,23 +34,22 @@ interface DefaultBeacon {
## Usage
-
+
Add the beacon plugin to a player:
```ts
-import { Player } from '@player-ui/player';
-import { BeaconPlugin } from '@player-ui/beacon-plugin';
+import { Player } from "@player-ui/player";
+import { BeaconPlugin } from "@player-ui/beacon-plugin";
const player = new Player({
plugins: [
new BeaconPlugin({
-
// Any plugins to the beacon-plugin
plugins: [],
// Callback to handle any beacon event
- callback: () => {}
+ callback: () => {},
}),
],
});
@@ -61,31 +59,30 @@ Beacons can be published directly by the plugin, but in most cases, a platform s
```ts
beaconPlugin.beacon({
- action: 'click',
- element: 'button',
- asset: asset // The entire Asset object, for use in the plugin pipeline
+ action: "click",
+ element: "button",
+ asset: asset, // The entire Asset object, for use in the plugin pipeline
// other metadata
});
```
-
-
+
+
Just like with the _core_ variant, to add support for beaconing in the `react` player, add the plugin to Player:
```ts
-import { ReactPlayer } from '@player-ui/react';
-import { BeaconPlugin } from '@player-ui/beacon-plugin-react';
+import { ReactPlayer } from "@player-ui/react";
+import { BeaconPlugin } from "@player-ui/beacon-plugin-react";
const player = new ReactPlayer({
plugins: [
new BeaconPlugin({
-
// Any plugins to the beacon-plugin
plugins: [],
// Callback to handle any beacon event
- callback: () => {}
+ callback: () => {},
}),
],
});
@@ -93,10 +90,11 @@ const player = new ReactPlayer({
This will add additional React Context to the running player for the producers from asset-libraries to leverage.
-
-
+
+
### CocoaPods
+
Add the subspec to your `Podfile`
```ruby
@@ -156,8 +154,8 @@ var body: some View {
}
```
-
-
+
+
Beaconing on the JVM platform (including Android) is done with an instance of the `BeaconPlugin`. By default, the Android Player includes a wrapper of the core beacon plugin. The Android Player can be configured to override the default BeaconPlugin by passing a different BeaconPlugin implementation on instantiation which can contain further configuration.
@@ -201,14 +199,14 @@ androidPlayer.beacon(
The base `RenderableAsset` class provides an additional helper to make beaconing less verbose from an asset perspective.
-[Helper in RenderableAsset](https://github.com/player-ui/player/blob/2a2110caf87ab752207c82ec9ab8ce72316d20f5/android/player/src/main/java/com/intuit/player/android/asset/RenderableAsset.kt#L253)
+[Helper in RenderableAsset](https://github.com/player-ui/player/blob/main/android/player/src/main/java/com/intuit/playerui/android/asset/RenderableAsset.kt#L253)
-
+
### Beacon Plugins
-Similar to how Player accepts plugins, the beacon-plugin itself accepts a list of plugins. These are able to mutate and augment the beacon payload as it makes its way through the publishing pipeline.
+Similar to how Player accepts plugins, the beacon-plugin itself accepts a list of plugins. These are able to mutate and augment the beacon payload as it makes its way through the publishing pipeline.
There are 3 hooks that are currently exposed:
@@ -235,30 +233,30 @@ The beacon plugin adds support for a `beacon` expression that can be referenced
### Assets
-
+
#### useBeacon hook
-The `@player-ui/beacon-plugin-react` package exports a hook that assets can leverage to publish beacons.
+The `@player-ui/beacon-plugin-react` package exports a hook that assets can leverage to publish beacons.
The `useBeacon` hook takes base options that apply broadly, and returns a function with those options as the base. You can then pass event specific information when calling `beacon`.
**Example**
```jsx
-import { useBeacon } from '@player-ui/beacon-plugin-react';
+import { useBeacon } from "@player-ui/beacon-plugin-react";
// inside of your asset
export const Component = (props) => {
- const beacon = useBeacon({ action: 'clicked', asset: props });
+ const beacon = useBeacon({ action: "clicked", asset: props });
return (
-
+
+
The SwiftUIBeaconPlugin attaches a BeaconContext to the root of the SwiftUI view tree as an environment value, so when included any asset can use that context to send a beacon, if the context is in the environment:
@@ -284,11 +282,11 @@ struct ActionAssetView: View {
}
```
-
+
-
+
- Using the base `RenderableAsset`'s helper function in this example fires off a basic beacon with no adjustment to format as well as empty data upon button click
+Using the base `RenderableAsset`'s helper function in this example fires off a basic beacon with no adjustment to format as well as empty data upon button click
**Example**
@@ -320,5 +318,5 @@ class MyAsset(assetContext: AssetContext) :
}
```
-
+
diff --git a/docs/site/pages/plugins/check-path.mdx b/docs/site/src/content/docs/plugins/multiplatform/check-path.mdx
similarity index 78%
rename from docs/site/pages/plugins/check-path.mdx
rename to docs/site/src/content/docs/plugins/multiplatform/check-path.mdx
index 84e993a8f..7f98c78f8 100644
--- a/docs/site/pages/plugins/check-path.mdx
+++ b/docs/site/src/content/docs/plugins/multiplatform/check-path.mdx
@@ -1,17 +1,16 @@
---
title: Check Path Plugin
-platform: react,core,android
---
-# Check Path Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
-The Check Path Plugin enables users to query segments of the view tree for contextual rendering or behavior.
+The Check Path Plugin enables users to query segments of the view tree for contextual rendering or behavior.
This is best suited to be referenced during the UI rendering phase, where one can make decisions about the rendering of an asset based on where it lies in the tree.
## Usage
-
+
Install the plugin:
@@ -22,7 +21,7 @@ yarn add @player-ui/check-path-plugin
Add it to Player:
```js
-import CheckPathPlugin from '@player-ui/check-path-plugin';
+import CheckPathPlugin from "@player-ui/check-path-plugin";
const checkPathPlugin = new CheckPathPlugin();
const player = new Player({ plugins: [checkPathPlugin] });
@@ -34,26 +33,27 @@ player.start(myFlow);
Then use the plugin to query the view:
```js
-const isCustomThing = checkPathPlugin.hasParentContext('my-asset-id', [
- 'input',
- 'myCustomViewType',
+const isCustomThing = checkPathPlugin.hasParentContext("my-asset-id", [
+ "input",
+ "myCustomViewType",
]);
```
-
-
+
+
Install the plugin:
```bash
yarn add @player-ui/check-path-plugin-react
```
+
6474792156
Add it to Player:
```js
-import { ReactPlayer } from '@player-ui/react';
-import { CheckPathPlugin } from '@player-ui/check-path-plugin-react';
+import { ReactPlayer } from "@player-ui/react";
+import { CheckPathPlugin } from "@player-ui/check-path-plugin-react";
const rp = new ReactPlayer({
plugins: [new CheckPathPlugin()],
@@ -62,9 +62,9 @@ const rp = new ReactPlayer({
This will automatically create the underlying _core_ version of the `CheckPathPlugin` to be made available via `React` Context for the hooks.
-
+
-
+
### CocoaPods
@@ -89,9 +89,10 @@ var body: some View {
)
}
```
-
-
+
+
+
In build.gradle
```kotlin
@@ -106,15 +107,15 @@ import com.intuit.playerui.plugins.checkpath.CheckPathPlugin
val plugins = listOf(CheckPathPlugin())
AndroidPlayer(plugins)
```
-
-
+
+
## API
-
+
### Query
@@ -125,13 +126,12 @@ This can either be a `function`, `string`, or an `object`.
- `object` - uses a partial-object match to query the object
- `function` - a filter that gets passed an object, and returns a boolean
-
There are a few different functions exposed by the plugin you can use:
### getParent
```ts
-function getParent(id: string, query: Query | Query[]): Asset | undefined
+function getParent(id: string, query: Query | Query[]): Asset | undefined;
```
The `getParent` method allows you to query up the tree, and return the first parent that matches the given query, or `undefined`.
@@ -142,7 +142,7 @@ If an array is passed, the tree is parsed matching on each query item from left
### getParentProp
```ts
-function getParentProp(id: string): string | undefined
+function getParentProp(id: string): string | undefined;
```
The `getParentProp` method returns the property on the parent object that the current object falls under.
@@ -153,7 +153,7 @@ For example, an `input` with a `text` asset as the label, will return `label` fo
### hasParentContext
```ts
-function hasParentContext(id: string, query: Query | Query[]): boolean
+function hasParentContext(id: string, query: Query | Query[]): boolean;
```
Similar to `getParent`, the `hasParentContext` method responds with the _existence_ of a parent with the given context.
@@ -163,14 +163,13 @@ Similar to `getParent`, the `hasParentContext` method responds with the _existen
### hasChildContext
```ts
-function hasChildContext(id: string, query: Query | Query[]): boolean
+function hasChildContext(id: string, query: Query | Query[]): boolean;
```
The compliment of `hasParentContext`, `hasChildContext` traverses _down_ the tree for _any_ path from the given node that satisfies the context requirements.
-
-
-
+
+
The API for the `React` version of the `CheckPathPlugin` is similar to the _core_ version, just exposed through `React` hooks for easy use in custom assets:
@@ -184,21 +183,21 @@ function useHasChildContext(id: string, query: Query | Query[]): boolean;
## Example
```tsx
-import { useHasParentContext } from '@player-ui/check-path-plugin-react';
+import { useHasParentContext } from "@player-ui/check-path-plugin-react";
export const MyAsset = ({ id }) => {
// If the asset is rendered within a form, render as a select instead of a radio button
- const isInForm = useHasParentContext(id, 'form');
+ const isInForm = useHasParentContext(id, "form");
return isInForm ? : ;
-}
+};
```
-
-
+
+
### Swift Usage
-The SwiftUICheckPathPlugin attaches the `BaseCheckPathPlugin` named `checkPath` to the root of the SwiftUI view tree as an environment value, so when included any asset can use that environment value to access the base functionality
+The SwiftUICheckPathPlugin attaches the `BaseCheckPathPlugin` named `checkPath` to the root of the SwiftUI view tree as an environment value, so when included any asset can use that environment value to access the base functionality
```swift
@@ -216,17 +215,16 @@ struct MyAsset: View {
}
```
-
-
+
+
+
The JVM CheckPathPlugin API contains partial functionality in comparison to the core plugin, ideally this should not be used, and all logic where pathing is concerned should be handled in transforms
If the situation arises and this plugin is absolutely necessary, the API from the following source are available at the moment. This is subject to change in future releases:
-[CheckPathPlugin](https://github.com/player-ui/player/blob/main/plugins/check-path/jvm/src/main/kotlin/CheckPathPlugin.kt)
+[CheckPathPlugin](https://github.com/player-ui/player/blob/main/plugins/check-path/jvm/src/main/kotlin/com/intuit/playerui/plugins/checkpath/CheckPathPlugin.kt)
-
+
-
-
diff --git a/docs/site/pages/plugins/console-logger.mdx b/docs/site/src/content/docs/plugins/multiplatform/console-logger.mdx
similarity index 68%
rename from docs/site/pages/plugins/console-logger.mdx
rename to docs/site/src/content/docs/plugins/multiplatform/console-logger.mdx
index d50835e00..ccb0fa3f9 100644
--- a/docs/site/pages/plugins/console-logger.mdx
+++ b/docs/site/src/content/docs/plugins/multiplatform/console-logger.mdx
@@ -1,40 +1,40 @@
---
title: Console Logger
-platform: react,core,ios
---
-# Console Logger Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
A plugin to easily enable logs to be written to the JS console. Extremely helpful for local Player development and debugging.
## Usage
-
+
Install the plugin:
```js
-import { Player } from '@player-ui/player';
-import { ConsoleLoggerPlugin } from '@player-ui/console-logger-plugin';
+import { Player } from "@player-ui/player";
+import { ConsoleLoggerPlugin } from "@player-ui/console-logger-plugin";
const consoleLogger = new ConsoleLoggerPlugin();
const player = new Player({
- plugins: [consoleLogger]
+ plugins: [consoleLogger],
});
```
To change the severity:
```js
-consoleLogger.setSeverity('warn');
+consoleLogger.setSeverity("warn");
```
-
-
+
+
### CocoaPods
+
Add the subspec to your `Podfile`
```ruby
@@ -56,9 +56,10 @@ var body: some View {
```
To change the severity, supply it as an argument to the constructor:
+
```swift
PrintLoggerPlugin(level: .warn)
```
-
-
\ No newline at end of file
+
+
diff --git a/docs/site/pages/plugins/external-action.mdx b/docs/site/src/content/docs/plugins/multiplatform/external-action.mdx
similarity index 89%
rename from docs/site/pages/plugins/external-action.mdx
rename to docs/site/src/content/docs/plugins/multiplatform/external-action.mdx
index e9caeec19..58e24c276 100644
--- a/docs/site/pages/plugins/external-action.mdx
+++ b/docs/site/src/content/docs/plugins/multiplatform/external-action.mdx
@@ -1,16 +1,15 @@
---
title: External Action
-platform: react,core,ios,android
---
-# External Action Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
-The External Action Plugin is an easy way to handle External states from the navigation of a Player flow.
+The External Action Plugin is an easy way to handle External states from the navigation of a Player flow.
## Usage
-
+
Install the plugin:
@@ -33,22 +32,21 @@ const externalActionHandler: ExternalStateHandler = async (state, options) => {
Add it to Player:
```js
-import { Player } from '@player-ui/player';
-import { ExternalActionPlugin } from '@player-ui/external-action-plugin';
+import { Player } from "@player-ui/player";
+import { ExternalActionPlugin } from "@player-ui/external-action-plugin";
const player = new Player({
- plugins: [
- new ExternalActionPlugin(externalActionHandler)
- ]
-})
+ plugins: [new ExternalActionPlugin(externalActionHandler)],
+});
```
This will transition any `EXTERNAL` state in Player's navigation, with a `ref` property of `custom` using the `next` transition.
-
-
+
+
### CocoaPods
+
Add the subspec to your `Podfile`
```ruby
@@ -116,8 +114,8 @@ var body: some View {
}
```
-
-
+
+
The `ExternalActionPlugin` adds support for handling `EXTERNAL` navigation states in the application. The handler, which can be provided during plugin initialization, receives three parameters:
@@ -126,12 +124,15 @@ The `ExternalActionPlugin` adds support for handling `EXTERNAL` navigation state
3. transition: `(String) -> Unit` is provided to enable the handler to "complete" the `EXTERNAL` state and transition using the provided `String` value
## Usage
+
In build.gradle
+
```kotlin
implementation "com.intuit.playerui.plugins:external-action:$PLAYER_VERSION"
```
In Player constructor
+
```kotlin
import com.intuit.playerui.plugins.externalAction.ExternalActionPlugin
@@ -157,6 +158,7 @@ androidPlayer.onExernalAction { /** handle external action */ }
```
In Player content
+
```json
{
"navigation": {
@@ -189,6 +191,7 @@ In Player content
Public API available from sources here:
-[ExternalActionPlugin](https://github.com/player-ui/player/blob/main/plugins/external-action/jvm/src/main/kotlin/com/intuit/player/plugins/externalAction/ExternalActionPlugin.kt)
-
-
\ No newline at end of file
+[ExternalActionPlugin](https://github.com/player-ui/player/blob/main/plugins/external-action/jvm/src/main/kotlin/com/intuit/playerui/plugins/externalAction/ExternalActionPlugin.kt)
+
+
+
diff --git a/docs/site/pages/plugins/metrics.mdx b/docs/site/src/content/docs/plugins/multiplatform/metrics.mdx
similarity index 81%
rename from docs/site/pages/plugins/metrics.mdx
rename to docs/site/src/content/docs/plugins/multiplatform/metrics.mdx
index d4e62d922..f6f869e4e 100644
--- a/docs/site/pages/plugins/metrics.mdx
+++ b/docs/site/src/content/docs/plugins/multiplatform/metrics.mdx
@@ -1,76 +1,77 @@
---
title: Metrics
-platform: core,react,ios,android
---
-# Metrics Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
+import Image from "../../../../components/Image.astro";
+import metricsTiming from "../../../../assets/metrics-timing.png";
The Metrics Plugin is used to gather timing information about Player's execution of a flow. There are also platform specific integrations to include `render` and `update` times.
The diagram below illistrates some of the timing information gathered:
-![Metrics Timing Diagram](/metrics-timing.png?darkModeInvert)
+
## Usage
-
+
Add the plugin to Player:
```js
-import { Player } from '@player-ui/player';
-import { MetricsPlugin } from '@player-ui/metrics-plugin';
+import { Player } from "@player-ui/player";
+import { MetricsPlugin } from "@player-ui/metrics-plugin";
const player = new Player({
plugins: [
new MetricsPlugin({
onUpdate: (metrics) => {
// Handle the update
- }
- })
- ]
-})
+ },
+ }),
+ ],
+});
```
The `onUpdate` callback will be invoked for any update to the metrics. There are also callbacks for finer-grained events (`onRenderEnd`, `onInteractive`, etc), as well as a `hooks` based API for even more control.
## Using a custom timer
-By default, all time is measured in ms using `performance.now()` with a fallback to the less-accurate `Date.now()`.
+By default, all time is measured in ms using `performance.now()` with a fallback to the less-accurate `Date.now()`.
If you wish to supply your own timer, simply use the `getTime` option to set the function to use.
-
## Measuring Render Time
For extensions of this plugin that wish to track the render (and update) times of nodes, add the `trackRenderTime` flag to `options`. You must then call `metrics.renderEnd()` to denote when content is painted on the screen. This is automatically handled for the platform specific versions of this plugin.
-
-
+
+
The `react` version of the Metrics Plugin adds support for `render` and `update` times to events. The API mirrors that of the core version:
```js
-import { ReactPlayer } from '@player-ui/react';
-import { MetricsPlugin } from '@player-ui/metrics-plugin-react';
+import { ReactPlayer } from "@player-ui/react";
+import { MetricsPlugin } from "@player-ui/metrics-plugin-react";
const player = new ReactPlayer({
plugins: [
new MetricsPlugin({
onUpdate: (metrics) => {
// Handle the update
- }
- })
- ]
-})
+ },
+ }),
+ ],
+});
```
-
-
+
+
The `ios` version of the Metrics Plugin will track initial render time for each view in a flow. Due to current SwiftUI limitations, update time can't be tracked yet. It can be used in conjunction with a core plugin that utilizes the events, through `findPlugin`, or standalone.
### CocoaPods
+
Add the subspec to your `Podfile`
```ruby
@@ -78,6 +79,7 @@ pod 'PlayerUI/MetricsPlugin'
```
### Swift Usage
+
```swift
var body: some View {
SwiftUIPlayer(
@@ -93,17 +95,20 @@ var body: some View {
)
}
```
-
-
+
+
+
The `JVM` Metrics plugin can track render time for views in a flow.
In build.gradle
+
```kotlin
implementation "com.intuit.playerui.plugins:metrics:$PLAYER_VERSION"
```
In Player constructor
+
```kotlin
import com.intuit.playerui.plugins.expression.ExpressionPlugin
@@ -112,14 +117,14 @@ val metricsPlugin = MetricsPlugin { timing, renderMetrics, flowMetrics ->
}
AndroidPlayer(metricsPlugin)
```
-
-
+
+
## Beaconing
-
+
The Metrics Plugin also includes a plugin for the Beacon Plugin that adds render time to the hook context for `viewed` beacons send for views. This plugin is automatically registered to the Beacon Plugin if the `trackRenderTime` option is enabled.
@@ -146,7 +151,7 @@ class MyBeaconPluginPlugin implements BeaconPluginPlugin {
}
```
-See the [Beacon Plugin](./beacon) for more info.
+See the [Beacon Plugin](/plugins/multiplatform/beacon) for more info.
-
-
\ No newline at end of file
+
+
diff --git a/docs/site/pages/plugins/partial-match-fingerprint.mdx b/docs/site/src/content/docs/plugins/multiplatform/partial-match-fingerprint.mdx
similarity index 67%
rename from docs/site/pages/plugins/partial-match-fingerprint.mdx
rename to docs/site/src/content/docs/plugins/multiplatform/partial-match-fingerprint.mdx
index 67c0ed8c9..399c8d3ec 100644
--- a/docs/site/pages/plugins/partial-match-fingerprint.mdx
+++ b/docs/site/src/content/docs/plugins/multiplatform/partial-match-fingerprint.mdx
@@ -1,53 +1,51 @@
---
title: Partial Match
-platform: core, ios
---
-# Partial Match Plugin
-
-This plugin enables users to map matches of assets to any arbitrary value in a partial-match-registry.
-For each asset in a resolved view, the matches will be computed.
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
+This plugin enables users to map matches of assets to any arbitrary value in a partial-match-registry.
+For each asset in a resolved view, the matches will be computed.
## Usage
-
+
Create a registry and add matches:
```ts
-import { Registry } from '@player-ui/partial-match-registry';
+import { Registry } from "@player-ui/partial-match-registry";
-const registry = new Registry([
- [{ type: 'action' }, 'ABC']
-])
+const registry = new Registry([[{ type: "action" }, "ABC"]]);
```
Add the registy to a plugin:
```ts
-import { Player } from '@player-ui/player';
-import { PartialMatchFingerprintPlugin } from '@player-ui/partial-match-fingerprint-plugin';
+import { Player } from "@player-ui/player";
+import { PartialMatchFingerprintPlugin } from "@player-ui/partial-match-fingerprint-plugin";
const matchPlugin = new PartialMatchFingerprintPlugin(registry);
const player = new Player({
- plugins: [matchPlugin]
-})
+ plugins: [matchPlugin],
+});
```
Query the plugin for matches:
```ts
-const value = matchPlugin.get('asset-id') // 'ABC'
+const value = matchPlugin.get("asset-id"); // 'ABC'
```
-
-
+
+
+
This plugin is used by `BaseAssetRegistry` to handle matching resolved asset nodes with their native implementation, to decode for rendering. It is unlikely to be needed to be used directly in iOS use cases.
### CocoaPods
+
Add the subspec to your `Podfile`
```ruby
@@ -55,6 +53,7 @@ pod 'PlayerUI'
```
### Swift Usage
+
```swift
let plugin = PartialMatchFingerprintPlugin()
@@ -65,5 +64,6 @@ plugin.register(match: ["type": "text"], index: 1)
// get the index for the asset with matching ID if it was resolved in the core plugin
plugin.get(assetId: "test")
```
-
-
\ No newline at end of file
+
+
+
diff --git a/docs/site/pages/plugins/pub-sub.mdx b/docs/site/src/content/docs/plugins/multiplatform/pub-sub.mdx
similarity index 82%
rename from docs/site/pages/plugins/pub-sub.mdx
rename to docs/site/src/content/docs/plugins/multiplatform/pub-sub.mdx
index 0061bc2ab..a9fe2bcf8 100644
--- a/docs/site/pages/plugins/pub-sub.mdx
+++ b/docs/site/src/content/docs/plugins/multiplatform/pub-sub.mdx
@@ -1,32 +1,31 @@
---
title: PubSub
-platform: core,react,ios,android
---
-# PubSub Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
-The PubSub plugin adds a publish/subscribe interface between the host app and Player's content.
+The PubSub plugin adds a publish/subscribe interface between the host app and Player's content.
## Usage
-
+
Add the plugin to Player:
```ts
-import { Player } from '@player-ui/player';
-import { PubSubPlugin } from '@player-ui/pub-sub-plugin';
+import { Player } from "@player-ui/player";
+import { PubSubPlugin } from "@player-ui/pub-sub-plugin";
const pubsub = new PubSubPlugin();
-const token = pubsub.subscribe('some-event', () => {
+const token = pubsub.subscribe("some-event", () => {
// Callback
});
const player = new Player({
- plugins: [pubsub]
-})
+ plugins: [pubsub],
+});
```
To unsubscribe:
@@ -35,12 +34,13 @@ To unsubscribe:
pubsub.unsubscribe(token);
```
-
-
+
+
If your content uses the `@[ publish() ]@` expression for actions, you can subscribe to these events by using the `PubSubPlugin`.
### CocoaPods
+
Add the subspec to your `Podfile`
```ruby
@@ -48,6 +48,7 @@ pod 'PlayerUI/PubSubPlugin'
```
### Swift Usage
+
```swift
let eventHandler: (String, AnyType?) -> Void = { (eventName, eventData) in
// Handle event
@@ -62,6 +63,7 @@ let plugin = PubSubPlugin([("eventName", eventHandler)], options: PubSubPluginOp
```
Then, just include it in your `plugins` to a Player instance:
+
```swift
var body: some View {
SwiftUIPlayer(
@@ -76,8 +78,8 @@ var body: some View {
_Note: AnyType is a custom enum type to handle the arbitrary types that can be received from these events, as the data is set in your Player Content, ensure that it matches either String, [String], or [String: String]._
-
-
+
+
The `PubSubPlugin` provides support for handling the publish expressions in Player content at the app level. The PubSubPlugin is included by default in the Android Player, so configuring events subscriptions can be done on Player using the provided extension methods.
@@ -88,6 +90,7 @@ The `PubSubPlugin` provides support for handling the publish expressions in Play
"exp": "@[ publish('some-event', {{foo.bar}}) ]@"
}
```
+
```kotlin
val player = AndroidPlayer(context)
@@ -98,16 +101,16 @@ val token = player.subscribe("some-event") { name: String, data: Any? ->
// handle event
}
-// extension method for removing a specific event subscription
+// extension method for removing a specific event subscription
player.unsubscribe(token)
```
-
+
## Publish Expression
-To trigger an event to be published, use the `publish()` expression in Player's content:
+To trigger an event to be published, use the `publish()` expression in Player's content:
```json
{
@@ -117,4 +120,4 @@ To trigger an event to be published, use the `publish()` expression in Player's
"exp": "@[ publish('some-event', 'some optional data') ]@""
}
}
-```
\ No newline at end of file
+```
diff --git a/docs/site/pages/plugins/shared-constants.mdx b/docs/site/src/content/docs/plugins/multiplatform/shared-constants.mdx
similarity index 54%
rename from docs/site/pages/plugins/shared-constants.mdx
rename to docs/site/src/content/docs/plugins/multiplatform/shared-constants.mdx
index be4299e64..68b372163 100644
--- a/docs/site/pages/plugins/shared-constants.mdx
+++ b/docs/site/src/content/docs/plugins/multiplatform/shared-constants.mdx
@@ -1,50 +1,48 @@
---
title: Shared Constants
-platform: core,react
---
-# Shared Constants Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
The Shared Constants Plugin enables users to define and override commonly used static values. It can be leveraged by other plugins to enable localization.
## Usage
-
+
Create the plugin and add it to Player:
```ts
-
-import { Player } from '@player-ui/player';
-import { ConstantsPlugin } from '@player-ui/shared-constants-plugin';
+import { Player } from "@player-ui/player";
+import { ConstantsPlugin } from "@player-ui/shared-constants-plugin";
const constantsPlugin = new ConstantsPlugin({
data: {
- prop1: 'A',
- prop2: 'B'
+ prop1: "A",
+ prop2: "B",
},
- namespace: 'constants',
- dataPath: 'data.constants'
+ namespace: "constants",
+ dataPath: "data.constants",
});
const player = new Player({
- plugins: [ constantsPlugin ]
+ plugins: [constantsPlugin],
});
```
You can then query the plugin to get the value of a particular key:
```js
-constantsPlugin.getConstants('prop1') // 'A'
+constantsPlugin.getConstants("prop1"); // 'A'
```
-
+
### Overriding Values in Content
-The `dataPath` configuration option enables content to override specific values for a particular flow:
+The `dataPath` configuration option enables content to override specific values for a particular flow:
```json
{
@@ -60,41 +58,40 @@ using a similar query for `prop1`, the value in the content takes precidence and
### Fallback Values
-Any query can also specify an optional _default_ value to return:
+Any query can also specify an optional _default_ value to return:
```js
-constantsPlugin.getConstants('prop3', 'default value') // 'default value'
+constantsPlugin.getConstants("prop3", "default value"); // 'default value'
```
## Examples
-### Common Types Plugin
+### Common Types Plugin
The Common Types Plugin leverages this pattern to allow for global contextual message overrides. In order to override those messages you may use something like:
```ts
-import { Player } from '@player-ui/player';
-import { ConstantsPlugin } from '@player-ui/constants-plugion';
-import { CommonTypesPlugin } from '@player-ui/common-types-plugin';
+import { Player } from "@player-ui/player";
+import { ConstantsPlugin } from "@player-ui/constants-plugion";
+import { CommonTypesPlugin } from "@player-ui/common-types-plugin";
const player = new Player({
plugins: [
new CommonTypesPlugin(),
new ConstantsPlugin({
- namespace: 'constants',
- dataPath: 'data.constants',
+ namespace: "constants",
+ dataPath: "data.constants",
data: {
validation: {
lengthError: {
- minimum: 'Way too short',
- maximum: 'Way too long',
- }
- }
- }
- })
- ]
+ minimum: "Way too short",
+ maximum: "Way too long",
+ },
+ },
+ },
+ }),
+ ],
});
```
-Any triggerd validation for the `length` validation will now use the custom error messages. See the [Common Types Plugin](./common-types) for more information on the supported overrides and paths.
-
+Any triggerd validation for the `length` validation will now use the custom error messages. See the [Common Types Plugin](/plugins/core/common-types) for more information on the supported overrides and paths.
diff --git a/docs/site/pages/plugins/auto-scroll-manager.mdx b/docs/site/src/content/docs/plugins/react/auto-scroll-manager.mdx
similarity index 56%
rename from docs/site/pages/plugins/auto-scroll-manager.mdx
rename to docs/site/src/content/docs/plugins/react/auto-scroll-manager.mdx
index 253182221..28632d1f2 100644
--- a/docs/site/pages/plugins/auto-scroll-manager.mdx
+++ b/docs/site/src/content/docs/plugins/react/auto-scroll-manager.mdx
@@ -1,51 +1,52 @@
---
title: Auto Scroll Manager Plugin
-platform: react
---
-# Auto Scroll Manager Plugin
+import PlatformTabs from "../../../../components/PlatformTabs.astro";
-The Auto Scroll Plugin helps orchestrate scrolling to components based off of 3 scenarios:
+The Auto Scroll Plugin helps orchestrate scrolling to components based off of 3 scenarios:
- On page load
- On validation trigger
- On first appearance after page load
-## Usage
+## Usage
-
+
Pull in the plugin and attach it to a player instance:
```tsx
-import { ReactPlayer } from '@player-ui/react';
-import { AutoScrollManagerPlugin } from '@player-ui/auto-scroll-manager-plugin-react';
+import { ReactPlayer } from "@player-ui/react";
+import { AutoScrollManagerPlugin } from "@player-ui/auto-scroll-manager-plugin-react";
const reactPlayer = new ReactPlayer({
- plugins: [new AutoScrollManagerPlugin()]
+ plugins: [new AutoScrollManagerPlugin()],
});
```
Next you'll use the provided `useRegisterAsScrollable` hook to register a component as a scrollable target in a `useLayoutEffect` or similar hook.
```tsx
-import { useRegisterAsScrollable, ScrollType } from '@player-ui/auto-scroll-manager-plugin-react';
+import {
+ useRegisterAsScrollable,
+ ScrollType,
+} from "@player-ui/auto-scroll-manager-plugin-react";
const CustomScrollableAsset = (props: CustomAssetType) => {
const registerFunction = useRegisterAsScrollable();
-
+
useLayoutEffect(() => {
registerFunction({
type: ScrollType.FirstAppearance,
- ref: props.id
- })
- }, [])
-
- return
-}
+ ref: props.id,
+ });
+ }, []);
+ return ;
+};
```
-
-
\ No newline at end of file
+
+
diff --git a/docs/site/pages/tools/cli.mdx b/docs/site/src/content/docs/tools/cli.mdx
similarity index 89%
rename from docs/site/pages/tools/cli.mdx
rename to docs/site/src/content/docs/tools/cli.mdx
index c040ec8f9..269c1e36a 100644
--- a/docs/site/pages/tools/cli.mdx
+++ b/docs/site/src/content/docs/tools/cli.mdx
@@ -2,9 +2,7 @@
title: CLI
---
-# CLI
-
-The `CLI` package is a simple way for users to interact with some of the build/validation tooling. As new capabilities are added to the ecosystem, they may be exposed via this cli to use of use for developers.
+The `CLI` package is a simple way for users to interact with some of the build/validation tooling. As new capabilities are added to the ecosystem, they may be exposed via this cli to use of use for developers.
## Config
@@ -24,10 +22,10 @@ Example:
```js
module.exports = {
- extends: '@my-scope/base',
+ extends: "@my-scope/base",
plugins: [
- 'plugin-npm-package',
- ['some-plugin-with-config', { config: true }],
+ "plugin-npm-package",
+ ["some-plugin-with-config", { config: true }],
{
// Plugins can also be defined inline
handler: () => {},
@@ -42,10 +40,10 @@ Options defined via the CLI arguments will take precedence over the config files
Plugins are the way to change runtime behavior of the CLI actions. This includes augmenting the behavior of the DSL compiler, language-service, and more.
-# Commands
+## Commands
- [`player dsl compile`](#player-dsl-compile)
-Compile Player DSL files into JSON after running TSC compiler against Typescript files
+ Compile Player DSL files into JSON after running TSC compiler against Typescript files
```
USAGE
@@ -64,11 +62,11 @@ DESCRIPTION
```
- [`player dsl validate`](#player-dsl-validate)
-Runs isolated TSC compiler on authored Player DSL Typescript files.
+ Runs isolated TSC compiler on authored Player DSL Typescript files.
```
USAGE
- $ player dsl validate [-f ] [-c ]
+ $ player dsl validate [-f ] [-c ]
FLAGS
-c, --config= Path to a specific config file to load.
@@ -80,7 +78,7 @@ DESCRIPTION
```
- [`player json validate`](#player-json-validate)
-Validate Player JSON content
+ Validate Player JSON content
```
USAGE
@@ -96,7 +94,7 @@ DESCRIPTION
```
- [`player dependency-versions check`](#player-dependency-versions-check)
-Checks for `@player-ui/@player-tools` dependency version mismatches and issues warnings/solutions accordingly
+ Checks for `@player-ui/@player-tools` dependency version mismatches and issues warnings/solutions accordingly
```
USAGE
@@ -116,4 +114,4 @@ DESCRIPTION
- `@player-ui/@player-tools` dependencies are fetched not only from inside the 'node_modules' at the top of the repository in which it is run but also from 'node_modules' in sub-directories.
For example, if you have some 'node_modules' inside of a 'packages' folder that contains `@player-ui/@player-tools` dependencies, then these will also be fetched.
The display of such dependencies also depends on the first bullet point.
-```
\ No newline at end of file
+```
diff --git a/docs/site/pages/tools/storybook.mdx b/docs/site/src/content/docs/tools/storybook.mdx
similarity index 81%
rename from docs/site/pages/tools/storybook.mdx
rename to docs/site/src/content/docs/tools/storybook.mdx
index fbaadbc7a..237e664d8 100644
--- a/docs/site/pages/tools/storybook.mdx
+++ b/docs/site/src/content/docs/tools/storybook.mdx
@@ -2,6 +2,12 @@
title: Player + Storybook Integration
---
+import Image from "../../../components/Image.astro";
+import eventsAddonGif from "../../../assets/tools/storybook/events-addon.gif";
+import flowAddonGif from "../../../assets/tools/storybook/flow-addon.gif";
+import docsAddonGif from "../../../assets/tools/storybook/docs-addon.gif";
+import flowResetGif from "../../../assets/tools/storybook/flow-reset.gif";
+
## Reference Assets
The reference asset set, complete with the storybook-plugin integration below is available [here](/storybook-demo)
@@ -60,19 +66,19 @@ export const parameters = {
The events panel addon shows a timeline of events as the flow is processed. Here you will see logs, render/update metrics, data mutations, and more.
-![Events Addon Panel](/tools/storybook/events-addon.gif)
+
#### Flow
The flow panel addon enables users to view and edit the JSON content in the running Player.
-![Flow Addon Panel](/tools/storybook/flow-addon.gif)
+
#### Asset Docs
The asset docs panel will show the data-types for the configured Assets.
-![Docs Addon Panel](/tools/storybook/docs-addon.gif)
+
In order to configure the panel to show specific asset documentation, first include the `assetXLRSources` as a parameter in your `preview.js`:
@@ -100,4 +106,4 @@ const meta: Meta = {
The reset button in the toolbar will reset the running Player with the initial content. This is useful for clearing any data or validation state, or for resetting a completed flow.
-![Flow Reset Button](/tools/storybook/flow-reset.gif)
+
diff --git a/docs/site/pages/xlr/concepts.mdx b/docs/site/src/content/docs/xlr/concepts.mdx
similarity index 88%
rename from docs/site/pages/xlr/concepts.mdx
rename to docs/site/src/content/docs/xlr/concepts.mdx
index 8cbe80fe2..93d0efd01 100644
--- a/docs/site/pages/xlr/concepts.mdx
+++ b/docs/site/src/content/docs/xlr/concepts.mdx
@@ -1,30 +1,29 @@
---
-title: XLR Concepts
+title: XLR Definitions
---
-# XLR Definitions
-
-When talking about anything its helpful to make sure everyone is on the same page, XLR is no exception. In this section we'll explore some concepts related to XLRs, how they work, and how they're used.
+When talking about anything its helpful to make sure everyone is on the same page, XLR is no exception. In this section we'll explore some concepts related to XLRs, how they work, and how they're used.
## Capability
-When we talk about a Capability, we are essentially talking about what it provides to Player. Most, if not all, capabilities are provided by Plugins. Capabilities are described in the manifest file in the `xlr` folder of a distribution. The manifest file, provided as both a `.json` and a `.js` file for static or dynamic use, contains the mapping of capabilities to a list of the XLRs.
+When we talk about a Capability, we are essentially talking about what it provides to Player. Most, if not all, capabilities are provided by Plugins. Capabilities are described in the manifest file in the `xlr` folder of a distribution. The manifest file, provided as both a `.json` and a `.js` file for static or dynamic use, contains the mapping of capabilities to a list of the XLRs.
## XLR Objects
-XLRs contain all of the information about a TypeScript type or interface. For an interface it will have the information on what parameters it has, the types of those parameters, and if those parameters are optional. For a type, it will similarly describe the properties/types that compose it. There is no distinction in XLR on whether the XLR came from a type or an interface as everything is just represented by a Node.
+XLRs contain all of the information about a TypeScript type or interface. For an interface it will have the information on what parameters it has, the types of those parameters, and if those parameters are optional. For a type, it will similarly describe the properties/types that compose it. There is no distinction in XLR on whether the XLR came from a type or an interface as everything is just represented by a Node.
### XLR Nodes
-XLR nodes are similar to TypeScripts internal AST nodes but a bit simpler. Almost every type/language feature you would use in TypeScript has an equivalent XLR node type. The definitions for these types are available in the `@player-tools/xlr` [package](https://github.com/player-ui/tools/tree/main/xlr/types).
+
+XLR nodes are similar to TypeScripts internal AST nodes but a bit simpler. Almost every type/language feature you would use in TypeScript has an equivalent XLR node type. The definitions for these types are available in the `@player-tools/xlr` [package](https://github.com/player-ui/tools/tree/main/xlr/types).
### Named Types
-Named Types represent a top level interface/type and can be _any_ XLR Node. Named types are generated from interfaces/types that are exported from a source file or plugin. It should be noted that when generating a Named Type, all referenced types are also serialized and included in place in the Named Type and *not* exported separately. That is unless The type is listed as a _Custom Primitive_. A reason to do this would be if that type definition changes based on use case or platform. For example, in the Player ecosystem `Asset` is considered a Custom Primitive because depending on the context, we might need to swap it out with a different type.
+Named Types represent a top level interface/type and can be _any_ XLR Node. Named types are generated from interfaces/types that are exported from a source file or plugin. It should be noted that when generating a Named Type, all referenced types are also serialized and included in place in the Named Type and _not_ exported separately. That is unless The type is listed as a _Custom Primitive_. A reason to do this would be if that type definition changes based on use case or platform. For example, in the Player ecosystem `Asset` is considered a Custom Primitive because depending on the context, we might need to swap it out with a different type.
# XLR SDK
-The XLR SDK is used to abstract away the more tedious interactions XLRs like loading them from their package, managing them when they're loaded, and validating content against them. The SDK does include an simple object store so that it can be used out of the box, however if your use case requires some different logic it can be extended quite easily. In fact, [we do that in the Player LSP](https://github.com/player-ui/tools/blob/main/language/service/src/xlr/registry.ts).
+The XLR SDK is used to abstract away the more tedious interactions XLRs like loading them from their package, managing them when they're loaded, and validating content against them. The SDK does include an simple object store so that it can be used out of the box, however if your use case requires some different logic it can be extended quite easily. In fact, [we do that in the Player LSP](https://github.com/player-ui/tools/blob/main/language/json-language-service/src/xlr/registry.ts).
## Transform Functions
-Transform functions can be used to modify XLRs when they're loaded and when they're exported. There is no real limit to what you can do in a transform function but typical use cases are things like adding new properties to object and substituting type references with different ones.
\ No newline at end of file
+Transform functions can be used to modify XLRs when they're loaded and when they're exported. There is no real limit to what you can do in a transform function but typical use cases are things like adding new properties to object and substituting type references with different ones.
diff --git a/docs/site/pages/xlr/intro.mdx b/docs/site/src/content/docs/xlr/intro.mdx
similarity index 89%
rename from docs/site/pages/xlr/intro.mdx
rename to docs/site/src/content/docs/xlr/intro.mdx
index 9cee7cca8..a1f82d7b3 100644
--- a/docs/site/pages/xlr/intro.mdx
+++ b/docs/site/src/content/docs/xlr/intro.mdx
@@ -17,8 +17,8 @@ How much you use XLR is pretty dependant on your niche in the Player ecosystem.
## As a TypeScript Plugin/Capability Author
-If you are developing Player capabilities for Core/React, all you need to do is have your Plugin fill in the `ExtendedPlayerPlugin` interface and run the Player CLI during build time and the CLI will take care of compiling and bundling the capabilities. You can see an example of this in the [Exporting Plugin Capabilities](./usage#exporting-plugin-capabilities) section.
+If you are developing Player capabilities for Core/React, all you need to do is have your Plugin fill in the `ExtendedPlayerPlugin` interface and run the Player CLI during build time and the CLI will take care of compiling and bundling the capabilities. You can see an example of this in the [Exporting Plugin Capabilities](/xlr/usage#exporting-plugin-capabilities) section.
## As Someone Building Capabilities Around Player
-If you want to leverage XLRs to develop capabilities around Player, you'll want to start with the [SDK](./concepts#xlr-sdk) and use it to load the XLRs from published packages. Then, using the SDK, you can access all the loaded types and information about them for use in your application.
\ No newline at end of file
+If you want to leverage XLRs to develop capabilities around Player, you'll want to start with the [SDK](/xlr/usage#sdk-usage) and use it to load the XLRs from published packages. Then, using the SDK, you can access all the loaded types and information about them for use in your application.
\ No newline at end of file
diff --git a/docs/site/pages/xlr/usage.mdx b/docs/site/src/content/docs/xlr/usage.mdx
similarity index 100%
rename from docs/site/pages/xlr/usage.mdx
rename to docs/site/src/content/docs/xlr/usage.mdx
diff --git a/docs/site/src/env.d.ts b/docs/site/src/env.d.ts
new file mode 100644
index 000000000..acef35f17
--- /dev/null
+++ b/docs/site/src/env.d.ts
@@ -0,0 +1,2 @@
+///
+///
diff --git a/docs/site/src/pages/tools/dsl-content-playground.astro b/docs/site/src/pages/tools/dsl-content-playground.astro
new file mode 100644
index 000000000..779cd0c05
--- /dev/null
+++ b/docs/site/src/pages/tools/dsl-content-playground.astro
@@ -0,0 +1,15 @@
+---
+import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
+import DSLContentPlayground from "../../components/tools/DSLContentPlayground";
+---
+
+
+
+ Content can be authored using JSON, or (preferred) with a TypeScript/React
+ API. Below is a sample editor where you can explore authoring content using
+ the DSL and our reference assets.
+
+
+
diff --git a/docs/site/src/pages/tools/view-ast-explorer.astro b/docs/site/src/pages/tools/view-ast-explorer.astro
new file mode 100644
index 000000000..96bf47149
--- /dev/null
+++ b/docs/site/src/pages/tools/view-ast-explorer.astro
@@ -0,0 +1,16 @@
+---
+import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
+import ASTExplorer from "../../components/tools/ASTExplorer";
+---
+
+
+
+ The internal representation of the View parses into an AST structure. This
+ is often used during the transform phase to edit the content prior to
+ rendering. Below is an interactive way of previewing the internal AST
+ representation for the given content.
+