| 1 | { |
| 2 | "data": { |
| 3 | "docs.bos-workspace.near": { |
| 4 | "widget": { |
| 5 | "home": { |
| 6 | "": "const LandingPageContainer = styled.div`\\\\n display: flex;\\\\n flex-direction: column;\\\\n align-items: center;\\\\n justify-content: center;\\\\n`;\\\\nconst Title = styled.h1`\\\\n font-size: 2.5rem;\\\\n color: #333;\\\\n margin-bottom: 2rem;\\\\n`;\\\\nconst Button = styled.button`\\\\n padding: 1rem 2rem;\\\\n font-size: 1.2rem;\\\\n background-color: #007bff;\\\\n color: #fff;\\\\n border: none;\\\\n border-radius: 5px;\\\\n cursor: pointer;\\\\n transition: background-color 0.3s ease;\\\\n &:hover {\\\\n background-color: #0056b3;\\\\n }\\\\n`;\\\\nconst BosWorkspaceInfo = styled.p`\\\\n text-align: center;\\\\n font-size: 1.1rem;\\\\n color: #444;\\\\n margin: 2rem;\\\\n`;\\\\nconst CodeSnippet = styled.div`\\\\n background-color: #f5f5f5;\\\\n padding: 0.5rem 1rem;\\\\n border-radius: 5px;\\\\n font-size: 0.9rem;\\\\n`;\\\\nreturn (\\\\n <LandingPageContainer>\\\\n <Title>bos-workspace</Title>\\\\n <BosWorkspaceInfo>\\\\n bos-workspace is a comprehensive toolset designed to simplify the\\\\n development and deployment of NEAR components and applications. With\\\\n support for hot reload, TypeScript, and multiple app management, it caters\\\\n to developers looking for an efficient and scalable developer environment.\\\\n </BosWorkspaceInfo>\\\\n <Title>Quickstart</Title>\\\\n <BosWorkspaceInfo>\\\\n To begin, either use this template repository or install bos-workspace\\\\n within an existing project:\\\\n </BosWorkspaceInfo>\\\\n <CodeSnippet>yarn add -D bos-workspace</CodeSnippet>\\\\n <BosWorkspaceInfo>\\\\n Then, you can clone widgets from an existing account via:\\\\n </BosWorkspaceInfo>\\\\n <CodeSnippet>bos-workspace clone [accountId]</CodeSnippet>\\\\n <BosWorkspaceInfo>\\\\n Or ensure the proper workspace structure and usage.\\\\n </BosWorkspaceInfo>\\\\n </LandingPageContainer>\\\\n);\\\\n" |
| 7 | }, |
| 8 | "index": { |
| 9 | "": "/**\\\\n * We can get some data from the project itself\\\\n * metadata, name, description, tags, etc.\\\\n * We want the document paths... We want to be able to add or remove them...\\\\n *\\\\n * What would be ideal for this? It can be a post or a page\\\\n * If it is a post, then we got comments on it directly.\\\\n *\\\\n * If you\\\\\\'d like to leave any questions, feel free to comment directly on the page.\\\\n *\\\\n * I want to be able to render some embeddings\\\\n */\\\\nconst config = {\\\\n theme: {\\\\n // add key values to define colors\\\\n // \\\\\\\"--main-color\\\\\\\": \\\\\\\"blue\\\\\\\",\\\\n // \\\\\\\"--secondary-color\\\\\\\": \\\\\\\"red\\\\\\\",\\\\n // background: \\\\\\\"var(--main-color)\\\\\\\",\\\\n // color: \\\\\\\"var(--secondary-color)\\\\\\\",\\\\n },\\\\n layout: {\\\\n src: \\\\\\\"devs.near/widget/Layout\\\\\\\",\\\\n props: {\\\\n variant: \\\\\\\"sidebar\\\\\\\",\\\\n },\\\\n },\\\\n blocks: {\\\\n // these get passed to the layout and children\\\\n Header: () => (\\\\n // customize your header\\\\n <Widget\\\\n src=\\\\\\\"docs.bos-workspace.near/widget/components.Header\\\\\\\"\\\\n props={{\\\\n routes: config.router.routes,\\\\n basePath: \\\\\\\"docs.bos-workspace.near/widget/index\\\\\\\",\\\\n param: \\\\\\\"page\\\\\\\",\\\\n ...props,\\\\n }}\\\\n />\\\\n ),\\\\n Footer: () => <></>, // customize your footer\\\\n Sidebar: () => (\\\\n <Widget\\\\n src=\\\\\\\"docs.bos-workspace.near/widget/components.Sidebar\\\\\\\"\\\\n props={{\\\\n routes: config.router.routes,\\\\n basePath: \\\\\\\"docs.bos-workspace.near/widget/index\\\\\\\",\\\\n param: \\\\\\\"page\\\\\\\",\\\\n ...props,\\\\n }}\\\\n />\\\\n ),\\\\n },\\\\n router: {\\\\n param: \\\\\\\"page\\\\\\\",\\\\n routes: [\\\\n {\\\\n path: \\\\\\\"/\\\\\\\",\\\\n element: {\\\\n src: \\\\\\\"docs.bos-workspace.near/widget/home\\\\\\\",\\\\n initialProps: {},\\\\n },\\\\n },\\\\n {\\\\n path: \\\\\\\"/settings\\\\\\\",\\\\n element: {\\\\n src: \\\\\\\"docs.bos-workspace.near/widget/settings\\\\\\\",\\\\n initialProps: {},\\\\n },\\\\n },\\\\n {\\\\n path: \\\\\\\"/:path*\\\\\\\",\\\\n element: {\\\\n src: \\\\\\\"docs.bos-workspace.near/widget/document\\\\\\\",\\\\n },\\\\n },\\\\n ],\\\\n },\\\\n};\\\\nconst Root = styled.div`\\\\n * {\\\\n box-sizing: border-box;\\\\n font-weight: 400;\\\\n }\\\\n .window {\\\\n /* -webkit-font-smoothing: none; */\\\\n letter-spacing: 0.025em;\\\\n background-color: #fff;\\\\n height: 100vh;\\\\n width: 100% !important;\\\\n border-radius: 5px;\\\\n padding-left: 1.5rem;\\\\n padding-right: 1.5rem;\\\\n }\\\\n .sidebar {\\\\n padding: 20px;\\\\n width: 250px;\\\\n }\\\\n .nested-section {\\\\n margin-bottom: 10px;\\\\n }\\\\n .parent-section {\\\\n margin-bottom: 5px;\\\\n }\\\\n .child-section {\\\\n margin-left: 20px; /* Adjust as needed for indentation */\\\\n }\\\\n .button {\\\\n display: block;\\\\n width: 100%;\\\\n padding: 8px;\\\\n margin: 0;\\\\n border: none;\\\\n /* background-color: transparent; */\\\\n text-align: left;\\\\n -moz-appearance: none;\\\\n appearance: none;\\\\n font-weight: 700;\\\\n letter-spacing: 0.05em;\\\\n padding: 0.45em 0.75em;\\\\n border-left: 2px solid #ededed;\\\\n border-top: 2px solid #ededed;\\\\n border-right: 2px solid #404040;\\\\n border-bottom: 2px solid #404040;\\\\n color: #000;\\\\n background-color: silver;\\\\n position: relative;\\\\n z-index: 10;\\\\n }\\\\n .button:hover {\\\\n background-color: #f0f0f0;\\\\n }\\\\n .separator {\\\\n border-bottom: 1px solid #ccc;\\\\n margin-bottom: 10px;\\\\n }\\\\n .link {\\\\n text-decoration: \\\\\\\"none\\\\\\\";\\\\n color: inherit;\\\\n }\\\\n .header {\\\\n width: 100%;\\\\n position: relative;\\\\n color: #fff;\\\\n padding: 0.25em 0.75em;\\\\n line-height: 1.4;\\\\n border-left: 2px solid #ededed;\\\\n border-top: 2px solid #ededed;\\\\n border-right: 2px solid #404040;\\\\n border-bottom: 2px solid #404040;\\\\n background: navy;\\\\n display: flex;\\\\n justify-content: space-between;\\\\n align-items: center;\\\\n padding: 10px 20px;\\\\n color: white;\\\\n .branding {\\\\n margin-right: 24px;\\\\n }\\\\n .nav {\\\\n display: flex;\\\\n flex-direction: row;\\\\n gap: 20px;\\\\n padding: 0 20px;\\\\n }\\\\n .end {\\\\n margin-left: auto;\\\\n }\\\\n }\\\\n .left-branding {\\\\n margin-right: auto; /* Pushes the branding to the left */\\\\n }\\\\n .routes {\\\\n display: flex;\\\\n gap: 20px;\\\\n }\\\\n .settings {\\\\n margin-left: auto; /* Pushes the settings to the right */\\\\n }\\\\n .link {\\\\n text-decoration: none;\\\\n color: white;\\\\n }\\\\n .link:hover {\\\\n text-decoration: underline;\\\\n }\\\\n .content {\\\\n flex: 1;\\\\n padding: 48px 96px;\\\\n margin: 20px auto;\\\\n height: 100%;\\\\n box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);\\\\n }\\\\n`;\\\\nreturn (\\\\n <Root>\\\\n <Widget\\\\n src=\\\\\\\"docs.bos-workspace.near/widget/PR.App\\\\\\\"\\\\n props={{ config, ...props }}\\\\n />\\\\n </Root>\\\\n);\\\\n" |
| 10 | }, |
| 11 | "PR.App": { |
| 12 | "": "const { Router } = VM.require(\\\\\\\"docs.bos-workspace.near/widget/PR.Router\\\\\\\") || {\\\\n Router: () => <></>,\\\\n};\\\\nconst { config, ...passProps } = props;\\\\nif (!config) {\\\\n // TODO: get from settings (or default)\\\\n config = {\\\\n router: {\\\\n param: \\\\\\\"page\\\\\\\",\\\\n routes: {\\\\n home: {\\\\n default: true,\\\\n path: \\\\\\\"efiz.near/widget/Tree\\\\\\\",\\\\n blockHeight: \\\\\\\"final\\\\\\\",\\\\n init: {\\\\n name: \\\\\\\"Home\\\\\\\",\\\\n },\\\\n },\\\\n },\\\\n },\\\\n blocks: {\\\\n Header: () => <></>, // customize your header\\\\n Footer: () => <></>, // customize your footer\\\\n },\\\\n };\\\\n} else {\\\\n // config may be a VM require string\\\\n if (typeof config !== \\\\\\\"object\\\\\\\") {\\\\n config = VM.require(config) || {};\\\\n }\\\\n}\\\\nconsole.log(\\\\\\\"config\\\\\\\", config);\\\\nif (!config) {\\\\n return (\\\\n <p>\\\\n unable to load config:{\\\\\\\" \\\\\\\"}\\\\n {typeof config === object ? JSON.stringify(config) : config}\\\\n </p>\\\\n );\\\\n}\\\\nconst Layout =\\\\n VM.require(config.layout?.src ?? \\\\\\\"devs.near/widget/Layout\\\\\\\") || (() => <></>);\\\\n// While something like Theme should be in the parent...\\\\nconst CSS = styled.div`\\\\n .container {\\\\n /* border: 1px solid red; */\\\\n }\\\\n .button {\\\\n }\\\\n .input {\\\\n }\\\\n .layout {\\\\n /* border: 4px solid var(--main-color); */\\\\n }\\\\n .header {\\\\n /* border: 1px solid blue; */\\\\n }\\\\n .content {\\\\n }\\\\n .footer {\\\\n }\\\\n`;\\\\nconst Container = styled.div`\\\\n display: flex;\\\\n height: 100%;\\\\n`;\\\\nconst Content = styled.div`\\\\n width: 100%;\\\\n height: 100%;\\\\n`;\\\\n// const Template = config.Template ?? (({children}) => <>{children}</>);\\\\nreturn (\\\\n <CSS style={config.theme}>\\\\n <Container className=\\\\\\\"window\\\\\\\">\\\\n <Layout\\\\n {...(config.layout?.props ?? { variant: \\\\\\\"standard\\\\\\\" })}\\\\n blocks={config.blocks}\\\\n >\\\\n <Content>\\\\n <Router config={config.router} {...passProps} />\\\\n </Content>\\\\n </Layout>\\\\n </Container>\\\\n </CSS>\\\\n);\\\\n" |
| 13 | }, |
| 14 | "document": { |
| 15 | "": "const { basePath, param, _params } = props;\\\\nconst { MarkdownViewer } = VM.require(\\\\\\\"devs.near/widget/markdown.view\\\\\\\") || {\\\\n MarkdownViewer: () => null,\\\\n};\\\\nconst { get } = VM.require(\\\\\\\"docs.bos-workspace.near/widget/utils.adapter\\\\\\\");\\\\nconst data = get(_params.path); // this is our adapter\\\\nif (!data) {\\\\n return <p>Page not found</p>;\\\\n}\\\\nreturn (\\\\n <div className=\\\\\\\"content\\\\\\\">\\\\n <h1>{data.title}</h1>\\\\n <MarkdownViewer value={data.content} />\\\\n </div>\\\\n);\\\\n" |
| 16 | }, |
| 17 | "settings": { |
| 18 | "": "const { MarkdownViewer } = VM.require(\\\\\\\"devs.near/widget/markdown.view\\\\\\\") || {\\\\n MarkdownViewer: () => null,\\\\n};\\\\nconst PageContainer = styled.div`\\\\n display: flex;\\\\n flex-direction: column;\\\\n height: 100vh;\\\\n`;\\\\nconst Header = styled.div`\\\\n background-color: #333;\\\\n padding: 20px;\\\\n display: flex;\\\\n justify-content: space-between;\\\\n`;\\\\nconst EditorWrapper = styled.div`\\\\n flex: 1;\\\\n padding: 96px;\\\\n box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);\\\\n`;\\\\nconst EditorTextarea = styled.textarea`\\\\n width: 100%;\\\\n height: 100%;\\\\n border: none;\\\\n font-size: 16px;\\\\n resize: none;\\\\n outline: none;\\\\n`;\\\\nconst PreviewContent = styled.div`\\\\n color: #333;\\\\n font-size: 16px;\\\\n`;\\\\nconst Select = styled.select``;\\\\nconst Option = styled.option``;\\\\nconst Label = styled.label`\\\\n margin-right: 10px;\\\\n`;\\\\nconst Button = styled.button`\\\\n // this could take in theme\\\\n padding: 10px 20px;\\\\n`;\\\\nconst ModalBox = styled.div`\\\\n background-color: white;\\\\n min-width: 400px;\\\\n max-width: 600px;\\\\n padding: 20px;\\\\n border-radius: 8px;\\\\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);\\\\n z-index: 1003;\\\\n`;\\\\nconst draftKey = \\\\\\\"draft\\\\\\\";\\\\nconst set = (k, v) => {\\\\n Storage.privateSet(k, v);\\\\n};\\\\nconst get = (k) => {\\\\n return Storage.privateGet(k);\\\\n};\\\\nconst draft = get(draftKey);\\\\nconst defaultViewMode = get(\\\\\\\"viewMode\\\\\\\");\\\\nconst defaultPreview = get(\\\\\\\"preview\\\\\\\");\\\\nconst defaultEditor = get(\\\\\\\"editor\\\\\\\");\\\\nconst defaultLanguage = get(\\\\\\\"language\\\\\\\");\\\\nconst defaultType = get(\\\\\\\"type\\\\\\\");\\\\nconst defaultPath = get(\\\\\\\"path\\\\\\\");\\\\nif (\\\\n draft === null ||\\\\n viewMode === null ||\\\\n defaultPreview === null ||\\\\n defaultEditor === null ||\\\\n defaultLanguage === null ||\\\\n defaultType === null ||\\\\n defaultPath === null\\\\n) {\\\\n return \\\\\\\"\\\\\\\";\\\\n}\\\\nconst [content, setContent] = useState(draft);\\\\nconst [viewMode, setViewMode] = useState(defaultViewMode || \\\\\\\"single\\\\\\\"); // \\\\\\'single\\\\\\' or \\\\\\'split\\\\\\'\\\\nconst [showPreview, setShowPreview] = useState(defaultPreview || false);\\\\nconst [type, setType] = useState(defaultType || \\\\\\\"\\\\\\\");\\\\nconst [editor, setEditor] = useState(defaultEditor || \\\\\\\"\\\\\\\");\\\\nconst [language, setLanguage] = useState(defaultLanguage || \\\\\\\"md\\\\\\\");\\\\nconst [path, setPath] = useState(defaultPath || \\\\\\\"\\\\\\\");\\\\nconst handleToggleViewMode = () => {\\\\n const newMode = viewMode === \\\\\\\"single\\\\\\\" ? \\\\\\\"split\\\\\\\" : \\\\\\\"single\\\\\\\";\\\\n set(\\\\\\\"viewMode\\\\\\\", newMode);\\\\n setViewMode(newMode);\\\\n set(\\\\\\\"preview\\\\\\\", false);\\\\n setShowPreview(false);\\\\n};\\\\nconst handleTogglePreview = () => {\\\\n set(\\\\\\\"preview\\\\\\\", !showPreview);\\\\n setShowPreview(!showPreview);\\\\n};\\\\nconst editors = [\\\\n {\\\\n value: \\\\\\\"\\\\\\\",\\\\n label: \\\\\\\"default textarea\\\\\\\",\\\\n },\\\\n {\\\\n value: \\\\\\\"devs.near/widget/markdown.SimpleMDE\\\\\\\",\\\\n label: \\\\\\\"SimpleMDE\\\\\\\",\\\\n },\\\\n {\\\\n value: \\\\\\\"devs.near/widget/markdown.MarkdownEditorIframe\\\\\\\",\\\\n label: \\\\\\\"MarkdownEditorIframe\\\\\\\",\\\\n },\\\\n];\\\\nconst languages = [\\\\n {\\\\n value: \\\\\\\"md\\\\\\\",\\\\n label: \\\\\\\"Markdown\\\\\\\",\\\\n },\\\\n {\\\\n value: \\\\\\\"json\\\\\\\",\\\\n label: \\\\\\\"JSON\\\\\\\",\\\\n },\\\\n];\\\\nconst types = [\\\\n {\\\\n value: \\\\\\\"document\\\\\\\",\\\\n label: \\\\\\\"Document\\\\\\\",\\\\n },\\\\n];\\\\nconst DefaultEditor = ({ value, onChange, onBlur }) => (\\\\n <EditorTextarea\\\\n placeholder=\\\\\\\"Start typing...\\\\\\\"\\\\n value={value}\\\\n onChange={onChange}\\\\n onBlur={onBlur}\\\\n />\\\\n);\\\\nreturn (\\\\n <PageContainer>\\\\n <Header>\\\\n <div>\\\\n {viewMode === \\\\\\\"single\\\\\\\" && (\\\\n <Button onClick={handleTogglePreview}>\\\\n {showPreview ? \\\\\\\"Hide Preview\\\\\\\" : \\\\\\\"Show Preview\\\\\\\"}\\\\n </Button>\\\\n )}\\\\n <Button onClick={handleToggleViewMode}>Toggle View Mode</Button>\\\\n </div>\\\\n <div>\\\\n <Widget\\\\n src=\\\\\\\"nui.sking.near/widget/Layout.Modal\\\\\\\"\\\\n props={{\\\\n open: state.saveModalOpen,\\\\n onOpenChange: (open) => {\\\\n State.update({\\\\n ...state,\\\\n saveModalOpen: open,\\\\n });\\\\n },\\\\n toggle: (\\\\n <Button className=\\\\\\\"classic\\\\\\\" disabled={!content}>\\\\n <>\\\\n <i className={\\\\\\\"bi bi-save\\\\\\\"} />\\\\n save\\\\n </>\\\\n </Button>\\\\n ),\\\\n content: (\\\\n <div className=\\\\\\\"w-100\\\\\\\">\\\\n <ModalBox>\\\\n <Widget\\\\n src={\\\\\\\"devs.near/widget/modal.create\\\\\\\"}\\\\n props={{\\\\n creatorId: context.accountId,\\\\n path: path,\\\\n setPath: (v) => {\\\\n setPath(v);\\\\n set(\\\\\\\"path\\\\\\\", v);\\\\n },\\\\n data: JSON.stringify({ body: content }),\\\\n closeModal: () => {\\\\n State.update({\\\\n ...state,\\\\n saveModalOpen: false,\\\\n });\\\\n },\\\\n }}\\\\n />\\\\n </ModalBox>\\\\n </div>\\\\n ),\\\\n }}\\\\n />\\\\n <Widget\\\\n src=\\\\\\\"nui.sking.near/widget/Layout.Modal\\\\\\\"\\\\n props={{\\\\n open: state.postModalOpen,\\\\n onOpenChange: (open) => {\\\\n State.update({\\\\n ...state,\\\\n postModalOpen: open,\\\\n });\\\\n },\\\\n toggle: (\\\\n <Button className=\\\\\\\"classic\\\\\\\" disabled={!path}>\\\\n <>\\\\n <i className={\\\\\\\"bi bi-send\\\\\\\"} />\\\\n post\\\\n </>\\\\n </Button>\\\\n ),\\\\n content: (\\\\n <div className=\\\\\\\"w-100\\\\\\\">\\\\n <ModalBox>\\\\n <Widget\\\\n src={\\\\\\\"devs.near/widget/modal.post\\\\\\\"}\\\\n props={{\\\\n creatorId: context.accountId,\\\\n path: path,\\\\n type: type,\\\\n closeModal: () => {\\\\n State.update({\\\\n ...state,\\\\n postModalOpen: false,\\\\n });\\\\n },\\\\n }}\\\\n />\\\\n </ModalBox>\\\\n </div>\\\\n ),\\\\n }}\\\\n />\\\\n </div>\\\\n </Header>\\\\n <div>\\\\n <Label>type:</Label>\\\\n <Select\\\\n onChange={(e) => {\\\\n set(\\\\\\\"type\\\\\\\", e.target.value);\\\\n setType(e.target.value);\\\\n }}\\\\n >\\\\n {types &&\\\\n types.map((it) => (\\\\n <Option value={it.value} selected={it.value === type}>\\\\n {it.label}\\\\n </Option>\\\\n ))}\\\\n </Select>\\\\n <Label>editor:</Label>\\\\n <Select\\\\n onChange={(e) => {\\\\n set(\\\\\\\"editor\\\\\\\", e.target.value);\\\\n setEditor(e.target.value);\\\\n }}\\\\n >\\\\n {editors &&\\\\n editors.map((it) => (\\\\n <Option value={it.value} selected={it.value === editor}>\\\\n {it.label}\\\\n </Option>\\\\n ))}\\\\n </Select>\\\\n <Label>language:</Label>\\\\n <Select\\\\n onChange={(e) => {\\\\n set(\\\\\\\"language\\\\\\\", e.target.value);\\\\n setLanguage(e.target.value);\\\\n }}\\\\n >\\\\n {languages &&\\\\n languages.map((it) => (\\\\n <Option value={it.value} selected={it.value === language}>\\\\n {it.label}\\\\n </Option>\\\\n ))}\\\\n </Select>\\\\n </div>\\\\n {viewMode === \\\\\\\"single\\\\\\\" ? (\\\\n <EditorWrapper key={editor}>\\\\n {showPreview ? (\\\\n <MarkdownViewer value={content} />\\\\n ) : (\\\\n <>\\\\n {editor ? (\\\\n <Widget\\\\n src={editor}\\\\n props={{\\\\n value: { content },\\\\n onChange: (v) => {\\\\n setContent(v);\\\\n set(draftKey, v);\\\\n },\\\\n }}\\\\n />\\\\n ) : (\\\\n <DefaultEditor\\\\n value={content}\\\\n onBlur={() => {\\\\n let v;\\\\n if (language === \\\\\\\"json\\\\\\\") {\\\\n v = JSON.stringify(JSON.parse(content), null, 2);\\\\n if (v !== \\\\\\\"null\\\\\\\") {\\\\n setContent(v);\\\\n set(draftKey, v);\\\\n }\\\\n }\\\\n }}\\\\n onChange={(e) => {\\\\n let v = e.target.value;\\\\n setContent(v);\\\\n Storage.privateSet(draftKey, v);\\\\n }}\\\\n />\\\\n )}\\\\n </>\\\\n )}\\\\n </EditorWrapper>\\\\n ) : (\\\\n <div style={{ display: \\\\\\\"flex\\\\\\\", height: \\\\\\\"100%\\\\\\\" }}>\\\\n <EditorWrapper>\\\\n {editor ? (\\\\n <Widget\\\\n src={editor}\\\\n props={{\\\\n value: { content },\\\\n onChange: (v) => {\\\\n setContent(v);\\\\n set(draftKey, v);\\\\n },\\\\n }}\\\\n />\\\\n ) : (\\\\n <DefaultEditor\\\\n value={content}\\\\n onBlur={() => {\\\\n let v;\\\\n if (language === \\\\\\\"json\\\\\\\") {\\\\n v = JSON.stringify(JSON.parse(content), null, 2);\\\\n if (v !== \\\\\\\"null\\\\\\\") {\\\\n setContent(v);\\\\n set(draftKey, v);\\\\n }\\\\n }\\\\n }}\\\\n onChange={(e) => {\\\\n let v = e.target.value;\\\\n setContent(v);\\\\n Storage.privateSet(draftKey, v);\\\\n }}\\\\n />\\\\n )}\\\\n </EditorWrapper>\\\\n <EditorWrapper>\\\\n <MarkdownViewer value={content} />\\\\n </EditorWrapper>\\\\n </div>\\\\n )}\\\\n </PageContainer>\\\\n);\\\\n" |
| 19 | }, |
| 20 | "PR.Router": { |
| 21 | "": "const { href } = VM.require(\\\\\\\"devs.near/widget/lib.url\\\\\\\") || {\\\\n href: () => \\\\\\\"/\\\\\\\",\\\\n};\\\\nconst Content = styled.div`\\\\n width: 100%;\\\\n height: 100%;\\\\n`;\\\\nfunction Router({ config, ...passProps }) {\\\\n const { routes, PageNotFound, debug, param } = config;\\\\n let activeRoute;\\\\n let activeRouteProps = {};\\\\n let params = {};\\\\n if (!param) param = \\\\\\\"page\\\\\\\";\\\\n const matchingRoute = routes.find((route) => {\\\\n // if no path is provided, match root path\\\\n if (passProps[param] === undefined && route.path === \\\\\\\"/\\\\\\\") {\\\\n return true;\\\\n } else if (passProps[param] === route.path.substring(1)) {\\\\n return true;\\\\n }\\\\n return false;\\\\n });\\\\n if (matchingRoute) {\\\\n activeRoute = matchingRoute;\\\\n } else {\\\\n // Fallback to dynamic path route if no other route matches\\\\n const dynamicPathRoute = routes.find((route) => {\\\\n const path = route.path.substring(1);\\\\n return path.startsWith(\\\\\\\":\\\\\\\") || path.startsWith(\\\\\\\"*\\\\\\\");\\\\n });\\\\n if (dynamicPathRoute) {\\\\n const key = dynamicPathRoute.path\\\\n .substring(1)\\\\n .replace(\\\\\\\"*\\\\\\\", \\\\\\\"\\\\\\\")\\\\n .replace(\\\\\\\":\\\\\\\", \\\\\\\"\\\\\\\");\\\\n activeRoute = dynamicPathRoute;\\\\n params = { _params: { [key]: passProps[param] || \\\\\\\"\\\\\\\" } };\\\\n } else {\\\\n activeRoute = PageNotFound;\\\\n }\\\\n }\\\\n if (activeRoute.element) {\\\\n activeRouteProps = {\\\\n ...activeRouteProps,\\\\n ...activeRoute.element.initialProps,\\\\n };\\\\n }\\\\n if (debug) {\\\\n return (\\\\n <div key={JSON.stringify(activeRoute)}>\\\\n <pre>{JSON.stringify(activeRoute, null, 2)}</pre>\\\\n <pre>{JSON.stringify(passProps, null, 2)}</pre>\\\\n </div>\\\\n );\\\\n } else {\\\\n return (\\\\n <Content key={param + JSON.stringify(activeRoute)}>\\\\n <Widget\\\\n src={activeRoute.element.src}\\\\n props={{ ...activeRouteProps, ...params }}\\\\n loading={<div style={{ height: \\\\\\\"100%\\\\\\\", width: \\\\\\\"100%\\\\\\\" }} />}\\\\n />\\\\n </Content>\\\\n );\\\\n }\\\\n}\\\\nreturn { Router };\\\\n" |
| 22 | }, |
| 23 | "utils.adapter": { |
| 24 | "": "const { normalize } = VM.require(\\\\\\\"devs.near/widget/lib.stringUtils\\\\\\\") || {\\\\n normalize: (str) => str,\\\\n};\\\\nconst data = {\\\\n \\\\\\\"\\\\\\\": JSON.stringify({\\\\n title: \\\\\\\"My Documentation\\\\\\\",\\\\n sections: [\\\\n {\\\\n title: \\\\\\\"Getting Started\\\\\\\",\\\\n content: `\\\\n ## Quickstart\\\\n To begin, either [use this template repository](https://github.com/new?template_name=quickstart&template_owner=NEARBuilders) or install \\\\\\\\`bos-workspace\\\\\\\\` within an existing project:\\\\n \\\\n \\\\\\\\`\\\\\\\\`\\\\\\\\`cmd\\\\n yarn add -D bos-workspace\\\\n \\\\\\\\`\\\\\\\\`\\\\\\\\`\\\\n \\\\n Then, you can clone widgets from an existing [account](https://near.social/mob.near/widget/Everyone) via:\\\\n \\\\n \\\\\\\\`\\\\\\\\`\\\\\\\\`bash\\\\n bos-workspace clone [accountId]\\\\n \\\\\\\\`\\\\\\\\`\\\\\\\\`\\\\n \\\\n Or ensure the proper workspace [structure and usage](#usage).\\\\n `,\\\\n subsections: [\\\\n {\\\\n title: \\\\\\\"Installation\\\\\\\",\\\\n content: \\\\\\\"# Instructions for installing the software.\\\\\\\",\\\\n },\\\\n {\\\\n title: \\\\\\\"Setup\\\\\\\",\\\\n content: \\\\\\\"Guidelines for setting up the environment.\\\\\\\",\\\\n },\\\\n ],\\\\n },\\\\n {\\\\n title: \\\\\\\"Usage\\\\\\\",\\\\n content: \\\\\\\"Hello 2\\\\\\\",\\\\n subsections: [\\\\n {\\\\n title: \\\\\\\"Basic Usage\\\\\\\",\\\\n content: \\\\\\\"Instructions for basic usage.\\\\\\\",\\\\n },\\\\n {\\\\n title: \\\\\\\"Advanced Usage\\\\\\\",\\\\n content: \\\\\\\"Instructions for advanced usage.\\\\\\\",\\\\n },\\\\n ],\\\\n },\\\\n {\\\\n title: \\\\\\\"Examples\\\\\\\",\\\\n content: \\\\\\\"Hello 3\\\\\\\",\\\\n subsections: [\\\\n {\\\\n title: \\\\\\\"Example 1\\\\\\\",\\\\n content: \\\\\\\"Description and usage of Example 1.\\\\\\\",\\\\n },\\\\n {\\\\n title: \\\\\\\"Example 2\\\\\\\",\\\\n content: \\\\\\\"Description and usage of Example 2.\\\\\\\",\\\\n },\\\\n ],\\\\n },\\\\n ],\\\\n }),\\\\n metadata: {\\\\n name: \\\\\\\"bos-workspace\\\\\\\",\\\\n description: `bos-workspace is a comprehensive toolset designed to simplify the\\\\n development and deployment of NEAR components and applications. With\\\\n support for hot reload, TypeScript, and multiple app management, it caters\\\\n to developers looking for an efficient and scalable developer environment.`,\\\\n },\\\\n};\\\\nconst documentation = JSON.parse(data[\\\\\\\"\\\\\\\"] || \\\\\\\"null\\\\\\\");\\\\nconst contentMap = {};\\\\n// Iterate over sections and subsections to populate content map\\\\ndocumentation.sections.forEach((section) => {\\\\n const sectionPath = normalize(section.title);\\\\n contentMap[sectionPath] = { title: section.title, content: section.content };\\\\n section.subsections.forEach((subsection) => {\\\\n const subsectionPath = `${sectionPath}/${normalize(subsection.title)}`;\\\\n contentMap[subsectionPath] = {\\\\n title: subsection.title,\\\\n content: subsection.content,\\\\n };\\\\n });\\\\n});\\\\nreturn {\\\\n get: (path) => {\\\\n if (path) {\\\\n return contentMap[path];\\\\n } else {\\\\n return contentMap;\\\\n }\\\\n },\\\\n create: (k, v) => {\\\\n console.log(\\\\\\\"create\\\\\\\");\\\\n },\\\\n};\\\\n" |
| 25 | }, |
| 26 | "components.Header": { |
| 27 | "": "const { basePath, param, page } = props;\\\\nreturn (\\\\n <div className=\\\\\\\"header\\\\\\\">\\\\n <div className=\\\\\\\"branding\\\\\\\">\\\\n <Link to={`/${basePath}`} className=\\\\\\\"link\\\\\\\">\\\\n <h3>bos-workspace</h3>\\\\n </Link>\\\\n </div>\\\\n <div className=\\\\\\\"nav\\\\\\\">\\\\n {/* <Link to={`/${basePath}?${param}=about`} className=\\\\\\\"link\\\\\\\">\\\\n about\\\\n </Link>\\\\n <Link to={`/${basePath}?${param}=contact`} className=\\\\\\\"link\\\\\\\">\\\\n contact\\\\n </Link> */}\\\\n </div>\\\\n <div className=\\\\\\\"end\\\\\\\">\\\\n {context.accountId === `docs.bos-workspace.near` && (\\\\n <>\\\\n {/* <Link\\\\n to={\\\\n props[param] === \\\\\\\"edit\\\\\\\"\\\\n ? `/${basePath}?${param}=${page}`\\\\n : `/${basePath}?${param}=edit&path=${page}`\\\\n }\\\\n className=\\\\\\\"link\\\\\\\"\\\\n >\\\\n <img\\\\n src=\\\\\\\"https://win98icons.alexmeub.com/icons/png/write_wordpad-1.png\\\\\\\"\\\\n alt=\\\\\\\"edit\\\\\\\"\\\\n width=\\\\\\\"32px\\\\\\\"\\\\n height=\\\\\\\"32px\\\\\\\"\\\\n aria-label=\\\\\\\"editor\\\\\\\"\\\\n title=\\\\\\\"editor\\\\\\\"\\\\n />\\\\n </Link> */}\\\\n <Link\\\\n to={\\\\n props[param] === \\\\\\\"settings\\\\\\\"\\\\n ? `/${basePath}`\\\\n : `/${basePath}?${param}=settings`\\\\n }\\\\n className=\\\\\\\"link\\\\\\\"\\\\n >\\\\n <img\\\\n src=\\\\\\\"https://win98icons.alexmeub.com/icons/png/settings_gear-0.png\\\\\\\"\\\\n alt=\\\\\\\"settings\\\\\\\"\\\\n width=\\\\\\\"32px\\\\\\\"\\\\n height=\\\\\\\"32px\\\\\\\"\\\\n aria-label=\\\\\\\"settings\\\\\\\"\\\\n title=\\\\\\\"settings\\\\\\\"\\\\n />\\\\n </Link>\\\\n </>\\\\n )}\\\\n </div>\\\\n </div>\\\\n);\\\\n" |
| 28 | }, |
| 29 | "components.Content": { |
| 30 | "": "" |
| 31 | }, |
| 32 | "components.Sidebar": { |
| 33 | "": "const { basePath, param } = props;\\\\nconst { get } = VM.require(\\\\\\\"docs.bos-workspace.near/widget/utils.adapter\\\\\\\");\\\\nconst documents = get();\\\\n// Preprocess documents to group paths by their parent sections\\\\nconst groupedSections = {};\\\\nObject.keys(documents).forEach((path) => {\\\\n const parts = path.split(\\\\\\\"/\\\\\\\");\\\\n const parentSection = parts[0];\\\\n const childSection = parts.length > 1 ? parts[1] : null;\\\\n\\\\n if (!groupedSections[parentSection]) {\\\\n groupedSections[parentSection] = [];\\\\n }\\\\n // Ensure child section is only added once per parent section\\\\n if (childSection && !groupedSections[parentSection].includes(childSection)) {\\\\n groupedSections[parentSection].push(childSection);\\\\n }\\\\n});\\\\nreturn (\\\\n <div className=\\\\\\\"sidebar\\\\\\\">\\\\n {Object.keys(groupedSections).map((parentSection) => (\\\\n <div key={parentSection}>\\\\n {/* Render parent section */}\\\\n <div className=\\\\\\\"parent-section\\\\\\\">\\\\n <Link to={`/${basePath}?${param}=${parentSection}`}>\\\\n <button className=\\\\\\\"button\\\\\\\">{documents[parentSection].title}</button>\\\\n </Link>\\\\n </div>\\\\n\\\\n {/* Render child sections */}\\\\n <div className=\\\\\\\"nested-section\\\\\\\">\\\\n {groupedSections[parentSection].map((childSection) => (\\\\n <div className=\\\\\\\"child-section\\\\\\\" key={childSection}>\\\\n <Link\\\\n to={`/${basePath}?${param}=${parentSection}/${childSection}`}\\\\n >\\\\n <button className=\\\\\\\"button\\\\\\\">\\\\n {documents[`${parentSection}/${childSection}`].title}\\\\n </button>\\\\n </Link>\\\\n </div>\\\\n ))}\\\\n </div>\\\\n\\\\n {/* Render separator */}\\\\n <div className=\\\\\\\"separator\\\\\\\"></div>\\\\n </div>\\\\n ))}\\\\n </div>\\\\n);\\\\n" |
| 34 | } |
| 35 | } |
| 36 | } |
| 37 | } |
| 38 | } |