├── .gitignore
├── .gitpod.yml
├── .prettierignore
├── LICENSE
├── components
├── Callout.js
├── ChannelCards.js
├── ChannelDiagram.js
├── Connector.js
├── Graypaper.js
├── IntroDiagram.js
├── KeyPopper.js
├── LinkDiagram.js
├── MatchDiagram.js
├── OrderCard.js
├── Patterns.js
├── PlatformAdder.js
├── PlatformCard.js
├── Sandpack.js
├── ShopCards.js
├── ShopDiagram.js
├── Steps.js
└── Video.js
├── next.config.js
├── package.json
├── pages
├── _app.js
├── _document.js
├── api-reference.mdx
├── channels.mdx
├── deployment.mdx
├── how-to-guides
│ ├── create-custom-channel.mdx
│ ├── create-custom-shop.mdx
│ ├── integrate-channel-platform.mdx
│ ├── integrate-shop-platform.mdx
│ └── meta.json
├── index.mdx
├── meta.json
└── shops.mdx
├── public
├── favicon
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── favicon.svg
│ ├── safari-pinned-tab.svg
│ └── site.webmanifest
└── images
│ ├── aliexpress.svg
│ ├── artificial-intelligence.jpg
│ ├── avatar.jpg
│ ├── bigcommerce.svg
│ ├── box.svg
│ ├── box2.svg
│ ├── cart.png
│ ├── channels.png
│ ├── channels.svg
│ ├── conti.jpeg
│ ├── conti2.png
│ ├── dashboard.svg
│ ├── deliverr.png
│ ├── deliverr.svg
│ ├── doordash.svg
│ ├── easypost.svg
│ ├── fulfillment.jpeg
│ ├── header-img-mobile.svg
│ ├── logoicon.svg
│ ├── magento.svg
│ ├── openship.svg
│ ├── printful.svg
│ ├── search.png
│ ├── shipbob.svg
│ ├── shipbobIcon.svg
│ ├── shiphero.svg
│ ├── shipheroFull.svg
│ ├── shipping.jpg
│ ├── shippo.svg
│ ├── shipstation.svg
│ ├── shipwire.svg
│ ├── shopify.svg
│ ├── shopifyIcon.svg
│ ├── shops.png
│ ├── shops.svg
│ ├── stripe.svg
│ ├── tracking.png
│ ├── volusion.svg
│ ├── webflow.svg
│ ├── wix.svg
│ └── woocommerce.svg
├── styles.css
├── theme.config.js
├── theme
├── InputWrapperStyles.js
├── extendTheme.js
├── globalStyles.js
└── styles.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .next
3 |
--------------------------------------------------------------------------------
/.gitpod.yml:
--------------------------------------------------------------------------------
1 | # This configuration file was automatically generated by Gitpod.
2 | # Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)
3 | # and commit this file to your remote git repository to share the goodness with others.
4 |
5 | tasks:
6 | - init: yarn install && yarn run build
7 | command: yarn run start
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | coverage/
3 | public/
4 | create-custom-channel.mdx
5 | create-custom-shop.mdx
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Openship documentation
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/components/Callout.js:
--------------------------------------------------------------------------------
1 | import { Notification, useMantineTheme } from "@mantine/core";
2 |
3 | export function Callout({ color, title, body, mt = "lg" }) {
4 | const theme = useMantineTheme();
5 | return (
6 |
24 | {body}
25 |
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/components/ChannelCards.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import {
3 | Stack,
4 | Modal,
5 | Accordion,
6 | Text,
7 | Divider,
8 | Code,
9 | Alert,
10 | List,
11 | Group,
12 | Button,
13 | Collapse,
14 | Box,
15 | useMantineTheme,
16 | Badge,
17 | Drawer,
18 | } from "@mantine/core";
19 | import { useSSG } from "nextra/ssg";
20 | import { PlatformCard } from "./PlatformCard";
21 | import { PlatformAdder } from "./PlatformAdder";
22 | import { IconAlertCircle } from "@tabler/icons";
23 | import { Prism } from "@mantine/prism";
24 | import { Callout } from "./Callout";
25 | import { Papercups } from "@papercups-io/chat-widget";
26 | import { useRouter } from "next/router";
27 | import { useEffect } from "react";
28 | import Image from "next/image";
29 | import { useTheme } from "next-themes";
30 |
31 | export const ChannelCards = () => {
32 | const { channels } = useSSG();
33 | const [channelIndex, setChannelIndex] = useState(null);
34 | const [showAlert, setShowAlert] = useState(true);
35 | const theme = useMantineTheme();
36 | const { theme: themeValue, setTheme, systemTheme } = useTheme();
37 |
38 | const router = useRouter();
39 |
40 | useEffect(() => {
41 | if (!router.isReady || !router.query.install) return;
42 | const paramChannel = channels.findIndex(
43 | ({ type }) => type === router.query.install
44 | );
45 | if (paramChannel !== "-1") {
46 | setChannelIndex(paramChannel);
47 | }
48 | }, [router.isReady, router.query.install]);
49 |
50 | const InstallationGuides = {
51 | Shopify: (
52 |
53 | ({
56 | label: { fontSize: 16, fontWeight: 400, lineHeight: 1.2 },
57 | item: { fontSize: 14 },
58 | // itemOpened: {
59 | // backgroundColor:
60 | // theme.colors.gray[theme.colorScheme === "dark" ? 9 : 0],
61 | // },
62 | })}
63 | >
64 |
65 | When adding the channel on Openship, choose SHOPIFY
as
66 | the type and click Connect Shopify:
67 |
84 | This will take you to Shopify to install Openship.
85 | }
87 | title={
88 |
89 | Openship's App Status
90 |
101 |
102 | }
103 | color="red"
104 | mt="xl"
105 | size="lg"
106 | pb={5}
107 | // variant="outline"
108 | sx={{
109 | border: `1px solid ${
110 | theme.colors.red[theme.colorScheme === "dark" ? 4 : 6]
111 | }`,
112 | boxShadow: theme.shadows.xs,
113 | }}
114 | styles={{ label: { width: "100%" } }}
115 | >
116 |
117 | When you install Openship on Shopify, you'll notice the app is
118 | unlisted.
119 |
120 |
121 | This is due to our pricing model. Shopify wants us to charge a
122 | fee for each Shopify channel our users connect. Openship charges
123 | 1 fee, allows unlimited channels, and supports e-commerce
124 | platforms outside of just Shopify. There are a pletora of apps
125 | in their app store that follow the same pricing model as us, but
126 | the playing field is not even.
127 |
128 |
129 | This wasn't an issue since unlisted apps could still be
130 | installed, but Shopify is removing this ability. They're forcing
131 | all apps to be installed from their App Store, adhere to their
132 | set pricing structure, while making exceptions for some apps
133 | along the way.
134 |
135 |
136 | Thankfully, installing this application is not the only way to
137 | use Shopify on Openship. You can create a custom app on your
138 | shop admin or create an app on the Shopify Partner dashboard.
139 | Read below to learn how.
140 |
141 |
142 |
143 |
147 | To create a custom app on Shopify, go to:
148 |
149 |
150 | https://your-domain.myshopify.com/admin/settings/apps
151 |
152 |
153 | And follow the video below:
154 |
162 |
163 |
164 | When setting the API scopes, these are the ones Openship needs
165 | access to:
166 |
167 |
168 | {[
169 | "read_orders",
170 | "write_orders",
171 | "read_products",
172 | "write_products",
173 | "read_fulfillments",
174 | "write_fulfillments",
175 | "write_draft_orders",
176 | "read_draft_orders",
177 | "read_assigned_fulfillment_orders",
178 | "write_assigned_fulfillment_orders",
179 | "read_merchant_managed_fulfillment_orders",
180 | "write_merchant_managed_fulfillment_orders",
181 | ].map((scope) => (
182 |
183 | {scope}
184 |
185 | ))}
186 |
187 |
188 | Once you have the Admin API access token copied, add a channel on
189 | Openship, choose
190 | SHOPIFY CUSTOM
as the channel type, choose a channel
191 | name, put your shopify domain as the domain, and Admin API access
192 | token under access token.
193 |
220 |
221 |
224 | Create a custom app on the Shopify Partner dashboard and add the
225 | credentials to .env
file
226 | >
227 | }
228 | >
229 | Take it one step further and allow users to install your{" "}
230 | Shopify app when they add a Shopify channel on Openship.
231 |
232 |
233 | To accomplish this, you'll need a free{" "}
234 |
239 | Shopify Partners
240 | {" "}
241 | account. After creating one, you'll need to create an app on the
242 | dashboard and get the API key and API secret key. You'll need to add
243 | this to your .env
file as{" "}
244 | CHANNEL_SHOPIFY_API_KEY
and{" "}
245 | CHANNEL_SHOPIFY_SECRET
respectively.
246 |
247 |
248 | {`CHANNEL_SHOPIFY_API_KEY=API_key
249 | CHANNEL_SHOPIFY_SECRET=API_secret_key`}
250 |
251 |
252 |
257 | If you're using Openship Cloud,{" "}
258 |
265 | get in touch
266 | {" "}
267 | and we'll add these variables to your instance.
268 |
269 | }
270 | />
271 |
272 |
273 |
274 | ),
275 | BigCommerce: (
276 |
277 | {/*
278 | Adding a Shopify shop to Openship can be done in 3 ways:
279 |
280 | */}
281 | ({
284 | label: { fontSize: 16, fontWeight: 400, lineHeight: 1.2 },
285 | item: { fontSize: 14 },
286 | // itemOpened: {
287 | // backgroundColor:
288 | // theme.colors.gray[theme.colorScheme === "dark" ? 9 : 0],
289 | // },
290 | })}
291 | >
292 |
293 | When adding the channel on Openship, choose BIGCOMMERCE
{" "}
294 | as the type and click Connect BigCommerce:
295 |
313 | This will take you to BigCommerce to install Openship.
314 |
315 |
318 | Create a custom app on the BigCommerce Developer dashboard and
319 | add the credentials to .env
file
320 | >
321 | }
322 | >
323 | Take it one step further and allow users to install your{" "}
324 | BigCommerce app when they add a BigCommerce channel on your Openship
325 | instance.
326 |
327 |
328 | To accomplish this, you'll need a free{" "}
329 |
334 | BigCommerce Partner
335 | {" "}
336 | account. After creating one, you'll need to create an app on the
337 | dashboard and get the API key and API secret key. You'll need to add
338 | this to your .env
file as{" "}
339 | CHANNEL_BIGCOMMERCE_API_KEY
and{" "}
340 | CHANNEL_BIGCOMMERCE_SECRET
respectively.
341 |
342 |
343 | {`CHANNEL_BIGCOMMERCE_API_KEY=API_key
344 | CHANNEL_BIGCOMMERCE_SECRET=API_secret_key`}
345 |
346 |
347 |
352 | If you're using Openship Cloud,{" "}
353 |
360 | get in touch
361 | {" "}
362 | and we'll add these variables to your instance.
363 |
364 | }
365 | />
366 |
367 |
368 |
369 | ),
370 | };
371 |
372 | return (
373 | <>
374 | setChannelIndex(null)}
377 | title={
378 |
379 |
385 | {channels[channelIndex]?.type}{" "}
386 |
387 |
388 | Installation Guide
389 |
390 | {/*
391 | 3 Options
392 | */}
393 |
394 | }
395 | size="lg"
396 | position="right"
397 | padding="md"
398 | styles={{
399 | root: { overflow: "scroll" },
400 | header: {
401 | marginLeft: -16,
402 | marginRight: -16,
403 | marginBottom: 0,
404 | marginTop: -16,
405 | padding: 16,
406 | background: themeValue === "light" ? "#ffffff" : "#000000",
407 | borderBottom: `1px solid ${
408 | themeValue === "light"
409 | ? theme.colors.gray[3]
410 | : theme.colors.gray[8]
411 | }`,
412 | },
413 | drawer: { overflow: "scroll" },
414 | }}
415 | >
416 | {InstallationGuides[channels[channelIndex]?.type]}
417 |
418 |
419 |
420 | {channels.map((channel, index) => (
421 | channel.stage === "DONE" && setChannelIndex(index)}
426 | />
427 | ))}
428 |
429 | >
430 | );
431 | };
432 |
--------------------------------------------------------------------------------
/components/ChannelDiagram.js:
--------------------------------------------------------------------------------
1 | import {
2 | Badge,
3 | Box,
4 | Divider,
5 | Group,
6 | Paper,
7 | ThemeIcon,
8 | useMantineTheme,
9 | Center,
10 | Space,
11 | Stack,
12 | } from "@mantine/core";
13 | import { IssueReopenedIcon } from "@primer/octicons-react";
14 | import { Bicycle } from "iconoir-react";
15 | import { Connector } from "./Connector";
16 | import { OrderCard } from "./OrderCard";
17 |
18 | export const ChannelDiagram = ({ activeImg }) => {
19 | const theme = useMantineTheme();
20 |
21 | return (
22 |
23 |
24 |
25 |
44 |
45 |
46 | ),
47 | },
48 | ]}
49 | />
50 |
51 |
70 |
71 |
72 | ),
73 | },
74 | ]}
75 | />
76 |
77 |
78 | ,
88 | },
89 | {
90 | name: "Tires",
91 | sku: "93443781",
92 | color: "green",
93 | icon: (
94 |
108 | ),
109 | },
110 | ]}
111 | />
112 |
113 |
114 |
115 | );
116 | };
117 |
--------------------------------------------------------------------------------
/components/Connector.js:
--------------------------------------------------------------------------------
1 | import { Box, Group, ThemeIcon, useMantineTheme } from "@mantine/core";
2 |
3 | export function Connector({ degrees, icon, bg = "#0f1134" }) {
4 | const theme = useMantineTheme();
5 |
6 | return (
7 |
8 |
20 |
26 |
35 | {icon}
36 |
37 | {/*
47 | Match
48 | */}
49 |
50 |
62 |
63 | );
64 | }
65 |
--------------------------------------------------------------------------------
/components/Graypaper.js:
--------------------------------------------------------------------------------
1 | import { Paper, useMantineTheme } from "@mantine/core";
2 |
3 | export const GrayPaper = ({ children, sx, p = "md", ...rest }) => {
4 | const theme = useMantineTheme();
5 | return (
6 | ({
12 | backgroundColor:
13 | theme.colorScheme === "dark"
14 | ? theme.colors.dark[8]
15 | : theme.fn.lighten(theme.colors.gray[0], 0.4),
16 | color:
17 | theme.colorScheme === "dark"
18 | ? theme.colors.dark[3]
19 | : theme.colors.gray[7],
20 | ...sx,
21 | })}
22 | {...rest}
23 | >
24 | {children}
25 |
26 | );
27 | };
28 |
--------------------------------------------------------------------------------
/components/IntroDiagram.js:
--------------------------------------------------------------------------------
1 | import { Box, Group, useMantineTheme, Space } from "@mantine/core";
2 | import { OrderCard } from "./OrderCard";
3 |
4 | export const IntroDiagram = ({ activeImg }) => {
5 | const theme = useMantineTheme();
6 |
7 | return (
8 |
30 |
49 |
50 |
51 | ),
52 | },
53 | {
54 | name: "Bike Pump",
55 | sku: "72384762",
56 | color: "violet",
57 | icon: (
58 |
69 | ),
70 | },
71 | ]}
72 | />
73 |
80 |
81 |
82 | {/* */}
94 |
106 |
107 |
108 |
109 |
110 | {/* */}
122 |
134 | {" "}
135 |
136 |
137 |
138 |
157 |
158 |
159 | ),
160 | },
161 | ]}
162 | />
163 |
171 |
190 |
191 |
192 | ),
193 | },
194 | ]}
195 | />
196 |
197 |
198 | );
199 | };
200 |
--------------------------------------------------------------------------------
/components/KeyPopper.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import {
3 | Box,
4 | Group,
5 | ActionIcon,
6 | useMantineTheme,
7 | Popper,
8 | Paper,
9 | Code,
10 | Button,
11 | Text,
12 | Center,
13 | } from "@mantine/core";
14 | import crypto from "crypto";
15 | import { KeyIcon, CopyIcon, SyncIcon, CheckIcon } from "@primer/octicons-react";
16 | import { useClipboard } from "@mantine/hooks";
17 |
18 | export function KeyPopper({ buttonColor, buttonBorder }) {
19 | const [referenceElement, setReferenceElement] = useState(null);
20 | const [value, setValue] = useState(null);
21 | const [visible, setVisible] = useState(true);
22 | const theme = useMantineTheme();
23 | const clipboard = useClipboard({ timeout: 1000 });
24 |
25 | async function createKey() {
26 | setValue(crypto.randomBytes(8).toString("hex"));
27 | }
28 |
29 | return (
30 |
31 | setVisible((m) => !m)}
44 | type="unset"
45 | >
46 |
47 |
48 |
49 |
57 |
69 | {value ? (
70 |
71 |
72 |
73 | {value}
74 | clipboard.copy(value)}
90 | >
91 | {clipboard.copied ? (
92 |
93 | ) : (
94 |
95 | )}
96 |
97 |
98 |
99 |
100 | await createKey()}
114 |
115 | // onClick={() =>
116 | // modals.openConfirmModal({
117 | // title: (
118 | //
130 | // Regenerate Key
131 | //
132 | // ),
133 | // centered: true,
134 | // children: (
135 | //
136 | // Are you sure you want to regenerate this key? This
137 | // action will invalidate your previous key and any
138 | // applications using the previous key will need to be
139 | // updated.
140 | //
141 | // ),
142 | // labels: {
143 | // confirm: "Regenerate Key",
144 | // cancel: "No don't regenerate it",
145 | // },
146 | // confirmProps: { color: "red" },
147 | // // onCancel: () => console.log("Cancel"),
148 | // onConfirm: createKey,
149 | // })
150 | // }
151 | >
152 |
153 |
154 |
155 | ) : (
156 | }
161 | onClick={async () => await createKey()}
162 | >
163 | GENERATE KEY
164 |
165 | )}
166 |
167 | {/* setVisible((m) => !m)}
180 | >
181 |
182 | */}
183 |
184 |
185 |
186 | );
187 | }
188 |
--------------------------------------------------------------------------------
/components/MatchDiagram.js:
--------------------------------------------------------------------------------
1 | import {
2 | Badge,
3 | Box,
4 | Divider,
5 | Group,
6 | Paper,
7 | ThemeIcon,
8 | useMantineTheme,
9 | Space,
10 | } from "@mantine/core";
11 | import { IssueReopenedIcon } from "@primer/octicons-react";
12 | import { Connector } from "./Connector";
13 | import { OrderCard } from "./OrderCard";
14 |
15 | export const MatchDiagram = ({ activeImg }) => {
16 | const theme = useMantineTheme();
17 |
18 | return (
19 |
41 |
60 |
61 |
62 | ),
63 | },
64 | {
65 | name: "Bike Pump",
66 | sku: "72384762",
67 | color: "violet",
68 | icon: (
69 |
80 | ),
81 | },
82 | ]}
83 | />
84 |
91 |
101 |
105 | Match
106 |
107 |
108 |
115 |
126 |
127 |
132 |
139 |
150 |
151 |
152 |
153 |
154 |
155 | } />
156 |
157 |
158 | } />
159 |
160 |
170 |
171 |
178 |
189 |
190 |
195 |
202 |
213 |
214 |
215 |
219 | Match
220 |
221 |
222 |
223 |
224 |
243 |
244 |
245 | ),
246 | },
247 | ]}
248 | />
249 |
257 |
276 |
277 |
278 | ),
279 | },
280 | ]}
281 | />
282 |
283 |
284 | );
285 | };
286 |
--------------------------------------------------------------------------------
/components/OrderCard.js:
--------------------------------------------------------------------------------
1 | import {
2 | Box,
3 | Group,
4 | Paper,
5 | Stack,
6 | Text,
7 | ThemeIcon,
8 | useMantineTheme,
9 | } from "@mantine/core";
10 | import { GrayPaper } from "./Graypaper";
11 |
12 | export function OrderCard({ title, order, lineItems, tracking, color }) {
13 | const theme = useMantineTheme();
14 |
15 | return (
16 |
17 |
25 |
26 |
33 |
34 |
35 | palette.purple[400],
44 | fontWeight: 600,
45 | letterSpacing: "0.06rem",
46 | width: "100%",
47 | color: theme.colors[color][6],
48 | fontSize: 12,
49 | [theme.fn.largerThan("xs")]: {
50 | fontSize: 16,
51 | },
52 | }}
53 | >
54 | {title}
55 |
56 |
72 | Order {order}
73 |
74 |
75 |
76 |
77 | {lineItems.map(({ name, sku, icon, color }) => (
78 |
89 |
90 |
110 | {icon}
111 |
112 |
113 |
121 | {name}
122 |
123 |
133 | SKU: {sku}
134 |
135 |
136 |
137 |
138 | ))}
139 |
140 |
141 | {tracking && tracking.map((a) => a)}
142 |
143 | );
144 | }
145 |
--------------------------------------------------------------------------------
/components/PlatformAdder.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import {
3 | Text,
4 | useMantineTheme,
5 | Box,
6 | Select,
7 | Modal,
8 | Paper,
9 | Center,
10 | Divider,
11 | Button,
12 | TextInput,
13 | Stack,
14 | } from "@mantine/core";
15 |
16 | export const PlatformAdder = ({
17 | title = "Channel",
18 | PlatformForms = {
19 | demo: {
20 | label: "Demo",
21 | fields: [
22 | {
23 | title: "Name",
24 | name: "name",
25 | placeholder: `Demo ${title}`,
26 | },
27 | ],
28 | buttonText: `Create ${title}`,
29 | },
30 | },
31 | maxWidth = 250,
32 | }) => {
33 | const theme = useMantineTheme();
34 | const [type, setType] = useState(Object.keys(PlatformForms)[0]);
35 |
36 | return (
37 |
38 |
39 |
53 | Create {title}
54 |
55 |
56 |
57 |
130 |
131 |
132 | );
133 | };
134 |
135 | export const Form = ({ label, fields, metaFields, buttonText }) => {
136 | const theme = useMantineTheme();
137 |
138 | return (
139 | <>
140 | {fields.map(({ name, title, placeholder, rightSection }) => (
141 |
164 | ))}
165 | {metaFields && (
166 |
177 |
178 |
186 | {label} fields
187 |
188 |
189 | {metaFields.map(
190 | ({ name, title, placeholder, rightSection }, index) => (
191 |
213 | )
214 | )}
215 |
216 | )}
217 |
218 |
243 |
244 | >
245 | );
246 | };
247 |
--------------------------------------------------------------------------------
/components/PlatformCard.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import {
3 | Box,
4 | useMantineTheme,
5 | Paper,
6 | Button,
7 | Badge,
8 | Popover,
9 | Tooltip,
10 | Stack,
11 | Text,
12 | Group,
13 | ActionIcon,
14 | Collapse,
15 | List,
16 | Code,
17 | } from "@mantine/core";
18 | import Image from "next/image";
19 | import { IconArrowUpRight, IconExternalLink } from "@tabler/icons";
20 | import { CheckIcon, GlobeIcon } from "@primer/octicons-react";
21 | import { GrayPaper } from "./Graypaper";
22 |
23 | export function PlatformCard({
24 | id,
25 | stage,
26 | type,
27 | image,
28 | upvotes,
29 | website,
30 | color = "teal",
31 | endpoint,
32 | onClick,
33 | }) {
34 | const [upvoteState, setUpvotes] = useState(upvotes);
35 | const [loading, setLoading] = useState(false);
36 | const [disabled, setDisabled] = useState(false);
37 | const [opened, setOpened] = useState(false);
38 |
39 | const theme = useMantineTheme();
40 | return (
41 | <>
42 |
52 |
53 |
118 |
119 |
123 |
124 | {type}
125 | ·
126 |
131 | {stage === "DONE" ? "READY" : stage}
132 |
133 | ·
134 | }
144 | >
145 |
153 |
159 |
160 |
161 | {/* }
169 | >
170 | Website
171 | */}
172 |
173 | {stage === "DONE" && (
174 |
175 | {/* */}
184 |
191 | Installation Guide
192 |
193 |
194 | )}
195 |
196 |
197 | Connect {type} to streamline order fulfillment
198 |
199 |
200 |
201 |
202 | >
203 | );
204 | }
205 |
--------------------------------------------------------------------------------
/components/Sandpack.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { SandpackClient } from "@codesandbox/sandpack-client";
3 | export function Preview({
4 | className,
5 | files,
6 | presetConfig,
7 | show,
8 | children,
9 | codeConfig,
10 | style,
11 | ...rest
12 | }) {
13 | return (
14 |
15 |
16 |
17 | );
18 | }
19 |
20 | function SandpackPreview({ files, presetConfig }) {
21 | const iframeRef = React.useRef(null);
22 | const clientRef = React.useRef(null);
23 |
24 | React.useEffect(() => {
25 | clientRef.current = new SandpackClient(
26 | iframeRef.current,
27 | {
28 | ...presetConfig,
29 | files: mergeFiles(presetConfig.files, files),
30 | },
31 | {
32 | showOpenInCodeSandbox: false,
33 | // showErrorScreen: false,
34 | // showLoadingScreen: false,
35 | }
36 | );
37 | }, []);
38 |
39 | React.useEffect(() => {
40 | if (clientRef.current) {
41 | clientRef.current.updatePreview({
42 | ...presetConfig,
43 | files: mergeFiles(presetConfig.files, files),
44 | });
45 | }
46 | }, [files]);
47 |
48 | return ;
49 | }
50 |
51 | function mergeFiles(csbFiles, chFiles) {
52 | const result = { ...csbFiles };
53 | chFiles.forEach((file) => {
54 | result["/" + file.name] = {
55 | code: file.code.lines
56 | .map((l) => l.tokens.map((t) => t.content).join(""))
57 | .join("\n"),
58 | };
59 | });
60 | return result;
61 | }
62 |
--------------------------------------------------------------------------------
/components/ShopDiagram.js:
--------------------------------------------------------------------------------
1 | import {
2 | Badge,
3 | Box,
4 | Divider,
5 | Group,
6 | Paper,
7 | ThemeIcon,
8 | useMantineTheme,
9 | Center,
10 | } from "@mantine/core";
11 | import { OrderCard } from "./OrderCard";
12 |
13 | export const ShopDiagram = ({ activeImg }) => {
14 | const theme = useMantineTheme();
15 |
16 | return (
17 |
18 |
19 |
38 |
39 |
40 | ),
41 | },
42 | {
43 | name: "Bike Pump",
44 | sku: "72384762",
45 | color: "violet",
46 | icon: (
47 |
58 | ),
59 | },
60 | ]}
61 | />
62 |
63 |
64 | );
65 | };
66 |
--------------------------------------------------------------------------------
/components/Steps.js:
--------------------------------------------------------------------------------
1 | import { Badge, List, Text, useMantineTheme } from "@mantine/core";
2 | import themeConfig from "../theme.config";
3 |
4 | export function Steps({ steps }) {
5 | return (
6 |
7 | {steps.map(({ text, badge, href }) => (
8 |
18 | // {index + 1}.
19 | //
20 | // }
21 | >
22 | {/* */}
23 |
24 | {badge.text}
25 |
26 | ({
31 | color: theme.colors.gray[theme.colorScheme === "dark" ? 3 : 7],
32 | ":hover": {
33 | // textDecoration: "underline",
34 | color: theme.colors.blue[theme.colorScheme === "dark" ? 4 : 5],
35 | },
36 | })}
37 | >
38 | {text}
39 |
40 | {/* */}
41 |
42 | ))}
43 |
44 | );
45 | }
46 |
--------------------------------------------------------------------------------
/components/Video.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import Image from "next/image";
3 | import { patterns } from "./Patterns";
4 | import { Box, Stack, Text, useMantineTheme } from "@mantine/core";
5 |
6 | export const Video = ({ videoId }) => {
7 | const [showVideo, setShowVideo] = useState(false);
8 | const theme = useMantineTheme();
9 | return (
10 |
11 | {showVideo ? (
12 |
13 |
23 |
27 |
28 |
29 | ) : (
30 |
31 |
43 |
44 |
49 |
50 |
159 |
160 | setShowVideo(true)}
162 | sx={{
163 | cursor: "pointer",
164 | position: "relative",
165 | width: 70,
166 | color: theme.colors.blue[9],
167 | }}
168 | >
169 |
180 |
181 |
188 | ...in 4 minutes
189 |
190 |
191 |
192 | )}
193 |
194 | );
195 | };
196 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | // const { remarkCodeHike } = require("@code-hike/mdx");
2 | // const theme = require("shiki/themes/nord.json");
3 | // const withNextra = require("nextra")({
4 | // theme: "nextra-theme-docs",
5 | // themeConfig: "./theme.config.js",
6 | // unstable_staticImage: true,
7 | // });
8 |
9 | // const withMDX = require("@next/mdx")({
10 | // extension: /\.mdx?$/,
11 | // options: {
12 | // remarkPlugins: [[remarkCodeHike, { theme }]],
13 | // },
14 | // });
15 |
16 | // module.exports = withMDX({
17 | // pageExtensions: ["ts", "tsx", "js", "jsx", "md", "mdx"],
18 | // eslint: { ignoreDuringBuilds: true },
19 | // });
20 |
21 | const { remarkCodeHike } = require("@code-hike/mdx");
22 | const theme = require("shiki/themes/material-ocean.json");
23 |
24 | const withNextra = require("nextra")({
25 | theme: "nextra-theme-docs",
26 | themeConfig: "./theme.config.js",
27 | mdxOptions: {
28 | remarkPlugins: [
29 | [
30 | remarkCodeHike,
31 | { theme, staticMediaQuery: "not screen, (max-width: 1080px)" },
32 | ],
33 | ],
34 | },
35 | unstable_flexsearch: true,
36 | unstable_staticImage: true,
37 | // unstable_staticImage: true
38 | });
39 | module.exports = withNextra({
40 | images: {
41 | domains: ["pbs.twimg.com", "avatars.githubusercontent.com", "i.imgur.com"],
42 | },
43 | });
44 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "docs",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "dev": "next dev",
8 | "build": "next build",
9 | "start": "next start"
10 | },
11 | "dependencies": {
12 | "@code-hike/mdx": "^0.7.1",
13 | "@mantine/core": "^4.2.9",
14 | "@mantine/hooks": "^4.2.9",
15 | "@mantine/next": "^4.2.9",
16 | "@mantine/prism": "^4.2.9",
17 | "@mdx-js/loader": "^2.0.0",
18 | "@next/mdx": "^12.1.0",
19 | "@papercups-io/chat-widget": "^1.3.1",
20 | "@primer/octicons-react": "^17.3.0",
21 | "@tabler/icons": "^1.78.1",
22 | "cookies-next": "^2.0.4",
23 | "crypto": "^1.0.1",
24 | "crypto-js": "^4.1.1",
25 | "iconoir-react": "^5.0.0",
26 | "next": "^12.1.0",
27 | "nextra": "2.0.0-alpha.54",
28 | "nextra-theme-docs": "2.0.0-alpha.54",
29 | "react": "^17.0.2",
30 | "react-dom": "^17.0.2",
31 | "react-intersection-observer": "^8.33.1"
32 | },
33 | "devDependencies": {
34 | "@types/react": "^17.0.40",
35 | "autoprefixer": "^10.4.2",
36 | "eslint": "^8.11.0",
37 | "eslint-config-next": "^12.1.0",
38 | "postcss": "^8.4.5",
39 | "typescript": "^4.6.2"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/pages/_app.js:
--------------------------------------------------------------------------------
1 | // import "@code-hike/mdx/dist/index.css"
2 | import { ChatWidget } from "@papercups-io/chat-widget";
3 | import { useEffect, useState } from "react";
4 | import Head from "next/head";
5 | import { useTheme } from "next-themes";
6 | import {
7 | Box,
8 | ColorSchemeProvider,
9 | Global,
10 | MantineProvider,
11 | } from "@mantine/core";
12 | import { useColorScheme } from "@mantine/hooks";
13 | import { theme as mantineTheme } from "../theme/extendTheme";
14 | import { styles } from "../theme/styles";
15 | // import "@code-hike/mdx/styles"
16 | import "nextra-theme-docs/style.css";
17 | import "../styles.css";
18 |
19 | function MantineTheme({ children }) {
20 | let { theme: themeValue, setTheme, systemTheme } = useTheme();
21 | let theme = themeValue === "system" ? systemTheme : themeValue;
22 |
23 | return (
24 |
25 | ({
31 | Input: { size: "md" },
32 | TextInput: { size: "md" },
33 | PasswordInput: { size: "md" },
34 | NumberInput: { size: "md" },
35 | })}
36 | styles={styles}
37 | >
38 | {children}
39 |
40 |
41 | );
42 | }
43 |
44 | export default function App(props) {
45 | const { Component, pageProps } = props;
46 | const [show, setShow] = useState(true);
47 | const getLayout = Component.getLayout || ((page) => page);
48 |
49 | return getLayout(
50 | <>
51 |
52 |
56 |
57 |
58 |
59 |
60 |
61 | setShow(false)}
72 | styles={{ chatContainer: { height: 500 } }}
73 | />
74 | >
75 | );
76 | }
77 |
--------------------------------------------------------------------------------
/pages/_document.js:
--------------------------------------------------------------------------------
1 | import Document, { Head, Html, Main, NextScript } from "next/document";
2 | import { createGetInitialProps } from "@mantine/next";
3 | import Script from "next/script";
4 |
5 | const getInitialProps = createGetInitialProps();
6 |
7 | export default class _Document extends Document {
8 | static getInitialProps = getInitialProps;
9 |
10 | render() {
11 | return (
12 |
13 |
14 |
19 |
20 |
21 |
22 |
23 |
27 |
30 |
31 |
32 | );
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/pages/api-reference.mdx:
--------------------------------------------------------------------------------
1 | # GraphQL Playground
2 |
3 | Each Openship instance has a GraphQL Playground at `/api/graphql`. Use it to get the API reference, interact with the API, and build integrations.
4 |
5 | For testing, use the development instance playground: https://devs.myopenship.com/api/graphql
6 |
7 | ## Accessing the API
8 |
9 | On the dashboard, generate an API key on the sidebar. Pass the key as a header named `x-api-key` for all API calls.
10 |
--------------------------------------------------------------------------------
/pages/channels.mdx:
--------------------------------------------------------------------------------
1 | import { ChannelCards } from "../components/ChannelCards";
2 |
3 | export const getStaticProps = ({ params }) => {
4 | return fetch(`https://openship.org/api/get-channels`)
5 | .then((res) => res.json())
6 | .then(({ channels }) => {
7 | return {
8 | props: {
9 | // We add an `ssg` field to the page props,
10 | // which will be provided to the Nextra `useSSG` hook.
11 | ssg: {
12 | channels,
13 | },
14 | },
15 | // The page will be considered as stale and regenerated every 60 seconds.
16 | // revalidate: 60,
17 | };
18 | });
19 | };
20 |
21 | # Introduction
22 |
23 | Channels represent destinations where your orders can be routed and fulfilled. This could be a supplier, 3PL, or even [custom channels](/how-to-guides/create-custom-channel).
24 |
25 |
26 |
--------------------------------------------------------------------------------
/pages/deployment.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Deployment
3 | ---
4 |
5 | import Bleed from "nextra-theme-docs/bleed";
6 | import { Box, Center } from "@mantine/core";
7 | import { Video } from "../components/Video";
8 | import { LinkDiagram } from "../components/LinkDiagram";
9 | import { IntroDiagram } from "../components/IntroDiagram";
10 | import { ShopDiagram } from "../components/ShopDiagram";
11 | import { ChannelDiagram } from "../components/ChannelDiagram";
12 | import { MatchDiagram } from "../components/MatchDiagram";
13 |
14 | # Self-hosting Openship
15 |
16 | ## Getting started
17 |
18 | Openship uses Next.js, so naturally, it can be hosted anywhere that supports Node.js. Openship also requires a `postgres` database.
19 |
20 | ### 1-Click Deployment
21 |
22 | These deployment services offer `Node.js` and `postgres` databases so Openship can be deployed in 1-click.
23 |
24 | #### Railway
25 |
26 | [](https://railway.app/new/template/31ZaPV?referralCode=fQpsld)
27 |
28 | #### Render
29 |
30 | [](https://render.com/deploy?repo=https://github.com/openshiporg/openship)
31 |
32 | ### Next.js Deployment
33 |
34 | To deploy on platforms that don't support databases like [Netlify](https://netlify.com) and [Vercel](https://vercel.com), you'll need to pass a `postgres` connection string as the `DATABASE_URL` variable.
35 |
36 | #### Vercel
37 |
38 | [](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fopenshiporg%2Fopenship&env=SESSION_SECRET,FRONTEND_URL,DATABASE_URL&envDescription=A%20postgres%20connection%20string%20is%20used%20for%20DATABASE_URL)
39 |
40 | #### Netlify
41 |
42 | [](https://app.netlify.com/start/deploy?repository=https://github.com/openshiporg/openship)
43 |
44 | Go to site settings > build & deploy > environment and add these variables:
45 |
46 | ```bash
47 | FRONTEND_URL=http://localhost:3000
48 | DATABASE_URL=postgresql://postgres:example@url:3000/postgres
49 | SESSION_SECRET=oh_please_please_change_me
50 | ```
51 |
52 | Replace DATABASE_URL with a postgres database connection string and FRONTEND_URL with the url ending in netlify.app. Redeploy the site.
53 |
--------------------------------------------------------------------------------
/pages/how-to-guides/meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "create-custom-shop": "Create a custom shop",
3 | "create-custom-channel": "Create a custom channel",
4 | "integrate-shop-platform": "Integrate shop platform",
5 | "integrate-channel-platform": "Integrate channel platform"
6 | }
7 |
--------------------------------------------------------------------------------
/pages/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Introduction
3 | ---
4 |
5 | import Bleed from "nextra-theme-docs/bleed";
6 | import { Box, Center } from "@mantine/core";
7 | import { Video } from "../components/Video";
8 | import { LinkDiagram } from "../components/LinkDiagram";
9 | import { IntroDiagram } from "../components/IntroDiagram";
10 | import { ShopDiagram } from "../components/ShopDiagram";
11 | import { ChannelDiagram } from "../components/ChannelDiagram";
12 | import { MatchDiagram } from "../components/MatchDiagram";
13 |
14 | # Openship
15 |
16 | ## Introduction
17 |
18 | Openship is an open-source fulfillment platform that enables e-commerce companies to create and leverage multi-channel fulfillment.
19 |
20 |
21 |
22 | ## Basic concepts
23 |
24 | ### Shops
25 |
26 | Shops represent your online stores where your customers place orders (e.g. Shopify, WooCommerce, eBay, Amazon). Once connected, new orders can be routed to Openship to be fulfilled.
27 |
28 |
29 |
30 | ### Channels
31 |
32 | Channels represent destinations where your orders can be routed and fulfilled. A channel could be an existing platform like your supplier's Shopify shop or a 3PL solution like FBA or ShipBob. It could also be something very simple like adding a row to a Google Sheet or sending an email with the order details. Openship currently only supports Shopify out of the box, but custom channels can be created. Check out [this guide](/how-to-guides/create-custom-channel) to learn more.
33 |
34 |
35 |
36 | ### Links
37 |
38 | Links represent a connection between a shop and a channel. Once linked, new shop orders are forwarded to the linked channel for fulfillment.
39 |
40 |
41 |
42 | ### Matches
43 |
44 | For finer control over the fulfillment process, matches can be created on the product level. Matches represent a connection between your shop products and your channel products. When a match is created between a shop product and channel product, Openship will automatically process that order. Matches can be easily changed between your channel products so you are not locked-in to any one vendor, supplier, or fulfillment system as you scale.
45 |
46 |
47 |
48 | ## Demo Video
49 |
50 |
58 |
--------------------------------------------------------------------------------
/pages/meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": "Introduction",
3 | "deployment": "Deployment",
4 | "how-to-guides": "How-to guides",
5 | "shops": "Shops",
6 | "channels": "Channels",
7 | "api-reference": "GraphQL API"
8 | }
9 |
--------------------------------------------------------------------------------
/pages/shops.mdx:
--------------------------------------------------------------------------------
1 | import { ShopCards } from "../components/ShopCards";
2 |
3 | export const getStaticProps = ({ params }) => {
4 | return fetch(`https://openship.org/api/get-shops`)
5 | .then((res) => res.json())
6 | .then(({ shops }) => {
7 | return {
8 | props: {
9 | // We add an `ssg` field to the page props
10 | // which will be provided to the Nextra `useSSG` hook.
11 | ssg: {
12 | shops,
13 | },
14 | },
15 | // The page will be considered as stale and regenerated every 60 seconds.
16 | // revalidate: 60,
17 | };
18 | });
19 | };
20 |
21 | # Introduction
22 |
23 | Shops represent online stores where your customers place orders. This includes e-commerce platforms, marketplaces, and even [custom shops](/how-to-guides/create-custom-shop).
24 |
25 |
26 |
--------------------------------------------------------------------------------
/public/favicon/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/favicon/android-chrome-192x192.png
--------------------------------------------------------------------------------
/public/favicon/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/favicon/android-chrome-512x512.png
--------------------------------------------------------------------------------
/public/favicon/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/favicon/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/favicon/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/favicon/favicon-16x16.png
--------------------------------------------------------------------------------
/public/favicon/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/favicon/favicon-32x32.png
--------------------------------------------------------------------------------
/public/favicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/favicon/favicon.ico
--------------------------------------------------------------------------------
/public/favicon/favicon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/favicon/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
23 |
--------------------------------------------------------------------------------
/public/favicon/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "",
3 | "short_name": "",
4 | "icons": [
5 | {
6 | "src": "/android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "/android-chrome-512x512.png",
12 | "sizes": "512x512",
13 | "type": "image/png"
14 | }
15 | ],
16 | "theme_color": "#ffffff",
17 | "background_color": "#ffffff",
18 | "display": "standalone"
19 | }
20 |
--------------------------------------------------------------------------------
/public/images/aliexpress.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
159 |
--------------------------------------------------------------------------------
/public/images/artificial-intelligence.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/images/artificial-intelligence.jpg
--------------------------------------------------------------------------------
/public/images/avatar.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/images/avatar.jpg
--------------------------------------------------------------------------------
/public/images/bigcommerce.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/box.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
69 |
--------------------------------------------------------------------------------
/public/images/box2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
90 |
--------------------------------------------------------------------------------
/public/images/cart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/images/cart.png
--------------------------------------------------------------------------------
/public/images/channels.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/images/channels.png
--------------------------------------------------------------------------------
/public/images/conti.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/images/conti.jpeg
--------------------------------------------------------------------------------
/public/images/conti2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/images/conti2.png
--------------------------------------------------------------------------------
/public/images/deliverr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/images/deliverr.png
--------------------------------------------------------------------------------
/public/images/deliverr.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/doordash.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/easypost.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/fulfillment.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/images/fulfillment.jpeg
--------------------------------------------------------------------------------
/public/images/logoicon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/magento.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/openship.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/printful.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/images/search.png
--------------------------------------------------------------------------------
/public/images/shipbob.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
55 |
--------------------------------------------------------------------------------
/public/images/shipbobIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/shiphero.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/shipheroFull.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
45 |
--------------------------------------------------------------------------------
/public/images/shipping.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/images/shipping.jpg
--------------------------------------------------------------------------------
/public/images/shippo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/shipstation.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/shipwire.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/shopify.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/shopifyIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/shops.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/images/shops.png
--------------------------------------------------------------------------------
/public/images/stripe.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/tracking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openshiporg/docs/2f8d588e87255fc12571a4e2291c382db4c68fb5/public/images/tracking.png
--------------------------------------------------------------------------------
/public/images/volusion.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/webflow.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/wix.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/woocommerce.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | [type="button"] {
2 | background-color: !important;
3 | }
4 |
5 | .ch-terminal {
6 | font-size: 14px;
7 | height: 100%;
8 | box-sizing: border-box;
9 | background: #1e1e1e;
10 | color: #fafafa;
11 | overflow: hidden;
12 | padding: 0 8px 8px;
13 | font-family: Ubuntu, Droid Sans, -apple-system, BlinkMacSystemFont, Segoe WPC,
14 | Segoe UI, sans-serif;
15 | }
16 | .ch-terminal-container .ch-frame-content {
17 | background-color: inherit;
18 | }
19 | .ch-terminal-prompt {
20 | color: #8fa2db;
21 | -webkit-user-select: none;
22 | -moz-user-select: none;
23 | -ms-user-select: none;
24 | user-select: none;
25 | }
26 | .ch-terminal-content {
27 | margin: 0;
28 | }
29 | .ch-terminal-output {
30 | opacity: 0.66;
31 | }
32 | .ch-code-line-number {
33 | -webkit-user-select: none;
34 | -moz-user-select: none;
35 | -ms-user-select: none;
36 | user-select: none;
37 | text-align: right;
38 | display: inline-block;
39 | box-sizing: border-box;
40 | padding-right: 1.5ch;
41 | font-variant-numeric: tabular-nums;
42 | }
43 | .ch-code-scroll-parent {
44 | display: block;
45 | font-weight: 400;
46 | font-size: 13px;
47 | line-height: 19px;
48 | letter-spacing: 0;
49 | border-radius: 0;
50 | background-color: unset;
51 | color: unset;
52 | padding: 0;
53 | box-sizing: content-box;
54 | border: none;
55 | width: unset !important;
56 | }
57 | .ch-code-scroll-parent ::-moz-selection {
58 | background-color: var(--ch-selection-background);
59 | color: inherit;
60 | }
61 | .ch-code-scroll-parent ::selection {
62 | background-color: var(--ch-selection-background);
63 | color: inherit;
64 | }
65 | .ch-code-button {
66 | position: absolute;
67 | top: 10px;
68 | right: 10px;
69 | width: 1.1em;
70 | height: 1.1em;
71 | cursor: pointer;
72 | }
73 | .ch-no-scroll {
74 | overflow: hidden;
75 | }
76 | .ch-expand-dialog {
77 | height: 100vh;
78 | width: 100vw;
79 | max-width: 900px;
80 | border: 0;
81 | background-color: transparent;
82 | }
83 | .ch-expand-dialog::-webkit-backdrop {
84 | background-color: rgba(0, 0, 0, 0.8);
85 | }
86 | .ch-expand-dialog::backdrop {
87 | background-color: rgba(0, 0, 0, 0.8);
88 | }
89 | .ch-expand-close {
90 | position: absolute;
91 | top: 10px;
92 | right: 10px;
93 | cursor: pointer;
94 | color: #fff;
95 | width: 26px;
96 | height: 26px;
97 | }
98 | .ch-expand-dialog-content {
99 | color: #fff;
100 | position: absolute;
101 | inset: 40px;
102 | overflow: hidden;
103 | border-radius: 8px;
104 | border: 1px solid;
105 | }
106 | .ch-code-browser {
107 | display: flex;
108 | height: 100%;
109 | font-family: Ubuntu, Droid Sans, -apple-system, BlinkMacSystemFont, Segoe WPC,
110 | Segoe UI, sans-serif;
111 | }
112 | .ch-code-browser-button {
113 | max-width: 20px;
114 | margin-left: auto;
115 | }
116 | .ch-code-browser-sidebar {
117 | border-right: 1px solid;
118 | min-width: 100px;
119 | padding: 1em 0;
120 | font-size: 0.95rem;
121 | }
122 | .ch-code-browser-content {
123 | overflow: auto;
124 | flex: 1;
125 | padding: 1em;
126 | white-space: pre;
127 | font-family: monospace;
128 | font-weight: 400;
129 | font-size: 1rem;
130 | line-height: 1.2rem;
131 | letter-spacing: 0;
132 | }
133 | .ch-code-browser-content ::-moz-selection {
134 | background-color: var(--ch-selection-background);
135 | color: inherit;
136 | }
137 | .ch-code-browser-content ::selection {
138 | background-color: var(--ch-selection-background);
139 | color: inherit;
140 | }
141 | .ch-code-browser-sidebar-file,
142 | .ch-code-browser-sidebar-folder {
143 | padding: 0.1em 1em;
144 | }
145 | .ch-code-browser-sidebar-file {
146 | cursor: pointer;
147 | }
148 | .ch-code-browser-sidebar-file:hover {
149 | background-color: var(--ch-hover-background);
150 | color: var(--ch-hover-foreground);
151 | }
152 | .ch-editor-tab {
153 | border-right: 1px solid #252526;
154 | min-width: -webkit-fit-content;
155 | min-width: -moz-fit-content;
156 | min-width: fit-content;
157 | flex-shrink: 1;
158 | position: relative;
159 | display: flex;
160 | white-space: nowrap;
161 | cursor: pointer;
162 | height: 100%;
163 | box-sizing: border-box;
164 | padding-left: 15px;
165 | padding-right: 15px;
166 | background-color: #2d2d2d;
167 | color: hsla(0, 0%, 100%, 0.5);
168 | min-width: 0;
169 | border-bottom: 1px solid;
170 | }
171 | .ch-editor-tab-active {
172 | background-color: #1e1e1e;
173 | color: #fff;
174 | min-width: unset;
175 | }
176 | .ch-editor-tab > div {
177 | margin-top: auto;
178 | margin-bottom: auto;
179 | font-size: 12px;
180 | line-height: 1.4em;
181 | text-overflow: ellipsis;
182 | overflow: hidden;
183 | }
184 | .ch-editor-frame {
185 | display: flex;
186 | flex-direction: column;
187 | position: relative;
188 | overflow: hidden;
189 | font-family: Ubuntu, Droid Sans, -apple-system, BlinkMacSystemFont, Segoe WPC,
190 | Segoe UI, sans-serif;
191 | -moz-column-break-inside: avoid;
192 | break-inside: avoid;
193 | --ch-title-bar-height: 30px;
194 | height: 100%;
195 | }
196 | .ch-editor-frame .ch-frame-title-bar {
197 | background: none;
198 | }
199 | .ch-editor-terminal {
200 | position: absolute;
201 | overflow: hidden;
202 | bottom: 0;
203 | width: 100%;
204 | background-color: #1e1e1e;
205 | color: #e7e7e7;
206 | border-top: 1px solid hsla(0, 0%, 50.2%, 0.35);
207 | padding: 0 8px;
208 | box-sizing: border-box;
209 | }
210 | .ch-editor-terminal-tab {
211 | text-transform: uppercase;
212 | padding: 4px 10px 3px;
213 | font-size: 11px;
214 | line-height: 24px;
215 | display: flex;
216 | }
217 | .ch-editor-terminal-tab > span {
218 | border-bottom: 1px solid #e7e7e7;
219 | }
220 | .ch-editor-terminal-content {
221 | margin-top: 8px;
222 | height: calc(100% - 40px);
223 | box-sizing: border-box;
224 | }
225 | .ch-editor-terminal-content .ch-terminal {
226 | font-size: 12px;
227 | margin: 0;
228 | }
229 | .ch-editor-button {
230 | width: 1.5em;
231 | height: 1.5em;
232 | cursor: pointer;
233 | min-width: 1.5em;
234 | min-height: 1.5em;
235 | margin-right: 0.8em;
236 | }
237 | .ch-frame {
238 | height: 100%;
239 | display: flex;
240 | flex-direction: column;
241 | }
242 | .ch-frame,
243 | .ch-simple-frame {
244 | font-family: Ubuntu, Droid Sans, -apple-system, BlinkMacSystemFont, Segoe WPC,
245 | Segoe UI, sans-serif;
246 | -moz-column-break-inside: avoid;
247 | break-inside: avoid;
248 | --ch-title-bar-height: 30px;
249 | }
250 | .ch-simple-frame {
251 | border-radius: 6px;
252 | overflow: hidden;
253 | box-shadow: 0 13px 27px -5px rgba(50, 50, 93, 0.25),
254 | 0 8px 16px -8px rgba(0, 0, 0, 0.3), 0 -6px 16px -6px rgba(0, 0, 0, 0.025);
255 | }
256 | .ch-frame-content {
257 | background-color: var(--ch-content-background, #fafafa);
258 | flex-grow: 1;
259 | flex-shrink: 1;
260 | flex-basis: 0;
261 | min-height: 0;
262 | }
263 | .ch-frame-zoom {
264 | --ch-frame-zoom: 1;
265 | overflow: auto;
266 | position: relative;
267 | width: calc(100% / var(--ch-frame-zoom));
268 | height: calc(100% / var(--ch-frame-zoom));
269 | transform: scale(var(--ch-frame-zoom));
270 | transform-origin: left top;
271 | }
272 | .ch-frame-title-bar {
273 | font-size: 12px;
274 | width: 100%;
275 | height: var(--ch-title-bar-height);
276 | min-height: var(--ch-title-bar-height);
277 | flex-grow: 0;
278 | flex-shrink: 0;
279 | display: flex;
280 | align-items: center;
281 | background-color: var(--ch-content-background, #252526);
282 | color: #ebebed;
283 | position: relative;
284 | }
285 | .ch-frame-middle-bar {
286 | text-overflow: ellipsis;
287 | overflow: hidden;
288 | white-space: nowrap;
289 | font-size: 1.2em;
290 | }
291 | .ch-frame-left-bar,
292 | .ch-frame-right-bar {
293 | flex-grow: 1;
294 | flex-basis: 1em;
295 | height: 100%;
296 | display: flex;
297 | align-items: center;
298 | width: -webkit-max-content;
299 | width: -moz-max-content;
300 | width: max-content;
301 | }
302 | .ch-frame-buttons {
303 | margin: 0 0.8em;
304 | flex-shrink: 0;
305 | height: 1em;
306 | width: 4.16em;
307 | display: flex;
308 | }
309 | .ch-frame-button {
310 | width: 1em;
311 | height: 1em;
312 | border: 0.08em solid;
313 | border-radius: 50%;
314 | display: inline-block;
315 | box-sizing: border-box;
316 | }
317 | .ch-frame-button-space {
318 | width: 0.56em;
319 | }
320 | .ch-frame-button-left {
321 | border-color: #ce5347;
322 | background-color: #ed6b60;
323 | }
324 | .ch-frame-button-middle {
325 | border-color: #d6a243;
326 | background-color: #f5be4f;
327 | }
328 | .ch-frame-button-right {
329 | border-color: #58a942;
330 | background-color: #62c554;
331 | }
332 | .ch-mini-browser {
333 | height: 100%;
334 | }
335 | .ch-mini-browser .ch-frame-content iframe,
336 | .ch-mini-browser .ch-frame-content video {
337 | border: none;
338 | position: absolute;
339 | height: 100%;
340 | width: 100%;
341 | }
342 | .ch-mini-browser .ch-frame-title-bar input {
343 | height: 1.4em;
344 | font-size: 1em;
345 | border-radius: 0.5em;
346 | border: none;
347 | box-shadow: none;
348 | flex: 1;
349 | padding: 0 10px;
350 | color: #544;
351 | min-width: 5px;
352 | width: 5px;
353 | }
354 | .ch-browser-button {
355 | margin: 0 1em;
356 | color: #999;
357 | }
358 | .ch-browser-back-button {
359 | margin-left: 0.2em;
360 | }
361 | .ch-browser-forward-button {
362 | margin-left: 0;
363 | }
364 | .ch-browser-open-button {
365 | color: inherit;
366 | }
367 | .ch-browser-open-icon {
368 | display: block;
369 | }
370 | .ch-spotlight {
371 | display: flex;
372 | gap: 0.5rem;
373 | margin: 1rem 0;
374 | }
375 | .ch-spotlight-tabs {
376 | display: flex;
377 | flex-flow: column;
378 | margin-right: 10px;
379 | flex: 1;
380 | gap: 0.5rem;
381 | align-items: stretch;
382 | }
383 | .ch-spotlight-tab {
384 | border-radius: 0.25rem;
385 | margin: 0 -0.5rem;
386 | padding: 0 0.5rem;
387 | border: 1px solid #e3e3e3;
388 | }
389 | .ch-spotlight-tab:hover {
390 | border-color: #222;
391 | }
392 | .ch-spotlight-tab[data-selected] {
393 | border-color: #0070f3;
394 | }
395 | .ch-spotlight-sticker {
396 | position: -webkit-sticky;
397 | position: sticky;
398 | top: 10vh;
399 | display: flex;
400 | align-self: stretch;
401 | flex-flow: column;
402 | justify-content: center;
403 | width: 420px;
404 | min-height: min(100%, 80vh);
405 | max-height: 80vh;
406 | }
407 | .ch-spotlight-sticker .ch-codeblock,
408 | .ch-spotlight-sticker .ch-codegroup {
409 | width: 100%;
410 | min-width: 100%;
411 | min-height: min(100%, 80vh);
412 | max-height: 80vh;
413 | margin-top: 0;
414 | margin-bottom: 0;
415 | flex: 1;
416 | }
417 | .ch-spotlight-with-preview .ch-spotlight-sticker {
418 | height: 80vh;
419 | gap: 0.5rem;
420 | }
421 | .ch-spotlight-with-preview .ch-spotlight-sticker .ch-codeblock,
422 | .ch-spotlight-with-preview .ch-spotlight-sticker .ch-codegroup {
423 | min-height: 0;
424 | flex: 1;
425 | }
426 | .ch-spotlight-with-preview .ch-spotlight-preview {
427 | height: 280px;
428 | }
429 | .ch-scrollycoding {
430 | display: flex;
431 | position: relative;
432 | margin: 1rem 0;
433 | padding-top: 1rem;
434 | }
435 | .ch-scrollycoding-content {
436 | box-sizing: border-box;
437 | padding-right: 24px;
438 | flex: 1;
439 | }
440 | .ch-scrollycoding-step-content {
441 | border-radius: 8px;
442 | margin: 0 -0.5rem;
443 | padding-right: 1rem;
444 | border: 1.5px solid transparent;
445 | min-height: 180px;
446 | opacity: 0.3;
447 | cursor: pointer;
448 | }
449 | .ch-scrollycoding-step-content[data-selected] {
450 | opacity: 1;
451 | }
452 | .ch-scrollycoding-step-content > :first-child {
453 | margin-top: 0;
454 | }
455 | .ch-scrollycoding-step-content > :last-child {
456 | margin-bottom: 0;
457 | }
458 | .ch-scrollycoding-sticker {
459 | position: -webkit-sticky;
460 | position: sticky;
461 | top: 10vh;
462 | display: flex;
463 | align-self: start;
464 | flex-flow: column;
465 | justify-content: center;
466 | width: var(--ch-scrollycoding-sticker-width, 420px);
467 | max-height: 80vh;
468 | }
469 | .ch-scrollycoding-with-preview .ch-scrollycoding-sticker {
470 | height: 80vh;
471 | gap: 0.5rem;
472 | }
473 | .ch-scrollycoding-with-preview .ch-scrollycoding-sticker .ch-codeblock,
474 | .ch-scrollycoding-with-preview .ch-scrollycoding-sticker .ch-codegroup {
475 | flex: 1;
476 | }
477 | .ch-scrollycoding-with-preview .ch-scrollycoding-preview {
478 | height: 280px;
479 | }
480 | .ch-scrollycoding-sticker .ch-codeblock,
481 | .ch-scrollycoding-sticker .ch-codegroup {
482 | width: 100%;
483 | min-width: 100%;
484 | min-height: var(--ch-scrollycoding-code-min-height, 200px);
485 | max-height: 80vh;
486 | margin-top: 0;
487 | margin-bottom: 0;
488 | }
489 | .ch-slideshow {
490 | margin: 1rem 0;
491 | }
492 | .ch-slideshow-slide {
493 | display: flex;
494 | flex-flow: row;
495 | gap: 0.5rem;
496 | align-items: stretch;
497 | aspect-ratio: 16/9;
498 | }
499 | .ch-slideshow-slide .ch-codeblock,
500 | .ch-slideshow-slide .ch-codegroup {
501 | flex: 2;
502 | margin-top: 0;
503 | margin-bottom: 0;
504 | height: auto;
505 | }
506 | .ch-slideshow .ch-slideshow-preview {
507 | flex: 1;
508 | height: auto;
509 | min-width: 0;
510 | }
511 | .ch-slideshow-range {
512 | display: flex;
513 | flex-flow: row;
514 | gap: 0.5rem;
515 | }
516 | .ch-slideshow-range input {
517 | flex: 1;
518 | }
519 | .ch-slideshow-notes {
520 | border-radius: 0.25rem;
521 | margin-top: 1rem;
522 | padding: 1rem;
523 | border: 1px solid #e3e3e3;
524 | }
525 | .ch-slideshow-note {
526 | min-height: 140px;
527 | max-height: 140px;
528 | padding: 0.05px;
529 | overflow: auto;
530 | }
531 | .ch-codeblock,
532 | .ch-codegroup,
533 | .ch-preview {
534 | border-radius: 6px;
535 | overflow: hidden;
536 | height: -webkit-max-content;
537 | height: -moz-max-content;
538 | height: max-content;
539 | box-shadow: 0 13px 27px -5px rgba(50, 50, 93, 0.25),
540 | 0 8px 16px -8px rgba(0, 0, 0, 0.3), 0 -6px 16px -6px rgba(0, 0, 0, 0.025);
541 | }
542 | .ch-codeblock > *,
543 | .ch-codegroup > *,
544 | .ch-preview > * {
545 | height: 100%;
546 | max-height: inherit;
547 | min-height: inherit;
548 | }
549 | .ch-codeblock,
550 | .ch-codegroup {
551 | margin-top: 1.25em;
552 | margin-bottom: 1.25em;
553 | }
554 | .ch-inline-code > code {
555 | padding: 0.2em 0.15em;
556 | margin: 0.1em -0.05em;
557 | border-radius: 0.25em;
558 | font-size: 0.9rem;
559 | }
560 | .ch-section-link,
561 | .ch-section-link * {
562 | text-decoration: underline;
563 | -webkit-text-decoration-style: dotted;
564 | text-decoration-style: dotted;
565 | text-decoration-thickness: 1px;
566 | -webkit-text-decoration-color: var(--ch-code-foreground, currentColor);
567 | text-decoration-color: var(--ch-code-foreground, currentColor);
568 | }
569 | .ch-section-link[data-active="true"] {
570 | background-color: rgba(186, 230, 253, 0.4);
571 | }
572 | .ch-section-link[data-active="true"],
573 | .ch-section-link[data-active="true"] * {
574 | text-decoration-thickness: 1.5px;
575 | }
576 |
--------------------------------------------------------------------------------
/theme.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | projectLink: 'https://github.com/openshiporg/docs',
3 | docsRepositoryBase: 'https://github.com/openshiporg/docs/blob/main', // docsRepository: '',
4 | titleSuffix: " – Openship",
5 | logo: (
6 | <>
7 |
11 |
120 |
121 |
122 | Multi-channel fulfillment
123 |
124 | >
125 | ),
126 | head: ({ title, meta }) => {
127 | return (
128 | <>
129 | {/* Favicons, meta */}
130 |
135 |
141 |
147 |
148 |
149 |
154 |
155 |
156 |
157 |
158 |
159 |
165 |
166 | >
167 | );
168 | },
169 | search: true,
170 | unstable_flexsearch: true,
171 | prevLinks: true,
172 | nextLinks: true,
173 | footer: true,
174 | footerEditOnGitHubLink: false,
175 | font: false,
176 | floatTOC: true,
177 | defaultMenuCollapsed: true,
178 | footerText: <>{new Date().getFullYear()} © Openship>,
179 | };
180 |
--------------------------------------------------------------------------------
/theme/InputWrapperStyles.js:
--------------------------------------------------------------------------------
1 | export const InputWrapperStyles = (theme) => ({
2 | root: {
3 | position: "relative",
4 | },
5 |
6 | input: {
7 | height: "auto",
8 | paddingTop: 18,
9 | paddingLeft: 13,
10 | border: `1px solid ${
11 | theme.colors.blueGray[theme.colorScheme === "dark" ? 7 : 2]
12 | }`,
13 | boxShadow: "0 1px 2px 0 rgb(0 0 0 / 0.05)",
14 | // fontSize: "16px !important",
15 | background:
16 | theme.colorScheme === "dark"
17 | ? theme.colors.dark[5]
18 | : theme.fn.lighten(theme.colors.blueGray[0], 0.5),
19 | "&:focus, &:focus-within": {
20 | outline: "none",
21 | borderColor: `${
22 | theme.colors[theme.primaryColor][theme.colorScheme === "dark" ? 8 : 5]
23 | } !important`,
24 | },
25 | WebkitAppearance: "none",
26 | },
27 |
28 | required: {
29 | display: "none",
30 | // ":before": { marginLeft: "auto", content: '" required"' },
31 | },
32 |
33 | error: {
34 | fontSize: 14,
35 | },
36 |
37 | label: {
38 | position: "absolute",
39 | pointerEvents: "none",
40 | color: theme.colors.blueGray[theme.colorScheme === "dark" ? 2 : 6],
41 | fontSize: theme.fontSizes.xs,
42 | paddingLeft: 14,
43 | paddingTop: 6,
44 | zIndex: 1,
45 | },
46 | });
47 |
--------------------------------------------------------------------------------
/theme/extendTheme.js:
--------------------------------------------------------------------------------
1 | export const theme = {
2 | colors: {
3 | green: [
4 | "#f0fdf4",
5 | "#dcfce7",
6 | "#bbf7d0",
7 | "#86efac",
8 | "#4ade80",
9 | "#22c55e",
10 | "#16a34a",
11 | "#15803d",
12 | "#166534",
13 | "#14532d",
14 | ],
15 | emerald: [
16 | "#ecfdf5",
17 | "#d1fae5",
18 | "#a7f3d0",
19 | "#6ee7b7",
20 | "#34d399",
21 | "#10b981",
22 | "#059669",
23 | "#047857",
24 | "#065f46",
25 | "#064e3b",
26 | ],
27 | blue: [
28 | "#eff6ff",
29 | "#dbeafe",
30 | "#bfdbfe",
31 | "#93c5fd",
32 | "#60a5fa",
33 | "#3b82f6",
34 | "#2563eb",
35 | "#1d4ed8",
36 | "#1e40af",
37 | "#1e3a8a",
38 | ],
39 | blueGray: [
40 | "#f8fafc",
41 | "#f1f5f9",
42 | "#e2e8f0",
43 | "#cbd5e1",
44 | "#94a3b8",
45 | "#64748b",
46 | "#475569",
47 | "#334155",
48 | "#1e293b",
49 | "#0f172a",
50 | ],
51 | },
52 | other: {
53 | sizes: {
54 | full: "100%",
55 | "3xs": "14rem",
56 | "2xs": "16rem",
57 | xs: "20rem",
58 | sm: "24rem",
59 | md: "28rem",
60 | lg: "32rem",
61 | xl: "36rem",
62 | "2xl": "42rem",
63 | "3xl": "48rem",
64 | "4xl": "56rem",
65 | "5xl": "64rem",
66 | "6xl": "72rem",
67 | "7xl": "80rem",
68 | "8xl": "90rem",
69 | },
70 | },
71 | };
72 |
--------------------------------------------------------------------------------
/theme/globalStyles.js:
--------------------------------------------------------------------------------
1 | export const globalStyles = {
2 | "#__next": {
3 | display: "flex",
4 | flexDirection: "column",
5 | minHeight: "100vh",
6 | },
7 | "#nprogress": { pointerEvents: "none" },
8 | "#nprogress .bar": {
9 | background: "#339AF0",
10 | position: "fixed",
11 | zIndex: 1031,
12 | top: "0",
13 | left: "0",
14 | width: "100%",
15 | height: "4px",
16 | },
17 | "#nprogress .peg": {
18 | display: "block",
19 | position: "absolute",
20 | right: "0px",
21 | width: "100px",
22 | height: "100%",
23 | // boxShadow: "0 0 10px red, 0 0 5px red",
24 | opacity: 1,
25 | WebkitTransform: "rotate(3deg) translate(0px, -4px)",
26 | msTransform: "rotate(3deg) translate(0px, -4px)",
27 | transform: "rotate(3deg) translate(0px, -4px)",
28 | },
29 | "#nprogress .spinner": {
30 | display: "block",
31 | position: "fixed",
32 | zIndex: 1031,
33 | top: "15px",
34 | right: "15px",
35 | },
36 | "#nprogress .spinner-icon": {
37 | width: "18px",
38 | height: "18px",
39 | boxSizing: "border-box",
40 | border: "solid 2px transparent",
41 | borderTopColor: "#339AF0",
42 | borderLeftColor: "#339AF0",
43 | borderRadius: "50%",
44 | WebkitAnimation: "nprogress-spinner 400ms linear infinite",
45 | animation: "nprogress-spinner 400ms linear infinite",
46 | },
47 | ".nprogress-custom-parent": {
48 | overflow: "hidden",
49 | position: "relative",
50 | },
51 | ".nprogress-custom-parent #nprogress .spinner,\n.nprogress-custom-parent #nprogress .bar":
52 | {
53 | position: "absolute",
54 | },
55 | "@-webkit-keyframes nprogress-spinner": {
56 | "0%": { WebkitTransform: "rotate(0deg)" },
57 | "100%": { WebkitTransform: "rotate(360deg)" },
58 | },
59 | "@keyframes nprogress-spinner": {
60 | "0%": { transform: "rotate(0deg)" },
61 | "100%": { transform: "rotate(360deg)" },
62 | },
63 | };
64 |
--------------------------------------------------------------------------------
/theme/styles.js:
--------------------------------------------------------------------------------
1 | import { InputWrapperStyles } from "./InputWrapperStyles";
2 |
3 | export const styles = {
4 | Drawer: (theme) => ({
5 | drawer: {
6 | background: theme.colorScheme === "light"
7 | ? theme.colors.blueGray[0]
8 | : theme.colors.dark[7],
9 | },
10 | }),
11 | TextInput: InputWrapperStyles,
12 | MultiSelect: InputWrapperStyles,
13 | Modal: (theme) => ({
14 | modal: {
15 | overflow: "hidden",
16 | },
17 | header: {
18 | background: theme.colors.gray[theme.colorScheme === "dark" ? 9 : 1],
19 | marginLeft: -20,
20 | marginRight: -20,
21 | marginTop: -20,
22 | paddingLeft: 24,
23 | paddingRight: 20,
24 | paddingTop: 16,
25 | paddingBottom: 14,
26 | borderBottom: `1px solid ${theme.colors.blueGray[theme.colorScheme === "dark" ? 9 : 2]}`,
27 | },
28 | }),
29 | };
30 |
--------------------------------------------------------------------------------