diff --git a/CHANGELOG.md b/CHANGELOG.md index e69eab238d6..7a75dfaafb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -225,12 +225,6 @@ - Calling `Path.join` with a second parameter to indicate that the resulting paths most be closed is now deprecated and will be removed in FreeSewing v4. -### react-components - -#### Added - - - This Pattern component now supports translation of nested arrays of strings, giving you more flexibility to concatenate translated parts of strings - ## 3.1.0 (2023-12-26) diff --git a/config/dependencies.yaml b/config/dependencies.yaml index bcb070f62b2..c43fea557da 100644 --- a/config/dependencies.yaml +++ b/config/dependencies.yaml @@ -124,7 +124,7 @@ plugintest: '@freesewing/plugin-sprinkle': *freesewing '@freesewing/plugin-svgattr': *freesewing '@freesewing/plugin-theme': *freesewing -react-components: +react: _: axios: *axios html-react-parser: "^5.0.7" @@ -399,7 +399,7 @@ sde: "@freesewing/plugin-theme": *freesewing "@freesewing/plugin-i18n": *freesewing "@freesewing/snapseries": *freesewing - "@freesewing/react-components": *freesewing + "@freesewing/react": *freesewing '@mdx-js/mdx': *mdx '@mdx-js/react': *mdx '@mdx-js/runtime': *mdxRuntime diff --git a/config/exceptions.yaml b/config/exceptions.yaml index 778c7d0f2cc..d4c59091998 100644 --- a/config/exceptions.yaml +++ b/config/exceptions.yaml @@ -6,7 +6,7 @@ customBuild: - new-design - prettier-config - core-plugins - - react-components + - react - rehype-jargon - rehype-highlight-lines skipTests: @@ -67,13 +67,14 @@ packageJson: prettier-config: type: 'module' exports: { .: './index.json' } - scripts: { build: 'echo "prettier-config: No build required" && exit 0' } + scripts: + build: 'echo "prettier-config: No build required" && exit 0' keywords: - prettier files: - index.json - package.json - react-components: + react: exports: ".": "internal": "./src/index.mjs" @@ -81,6 +82,22 @@ packageJson: "./linedrawings": "./src/linedrawings/index.mjs" "./pattern": "./src/pattern/index.mjs" "./xray": "./src/pattern-xray/index.mjs" + "./config/freesewing": "./config/freesewing/index.mjs" + # Context + "./context/loadingStatus": "./context/loadingStatus/index.mjs" + # Hooks + "./hooks/useBackend": "./hooks/useBackend/index.mjs" + # Lib + "./lib/RestClient": "./lib/RestClient/index.mjs" + files: + - "components/**" + - "hooks/**" + - "lib/**" + - "README.md" + scripts: + lint: "eslint 'components/**/*.mjs' 'hooks/**/*.mjs' 'lib/**/*.mjs' 'context/**/*.mjs' 'config/**/*.mjs'" + prettier: "npx prettier --write 'components/**/*.mjs' 'hooks/**/*.mjs' 'lib/**/*.mjs' 'context/**/*.mjs' 'config/**/*.mjs'" + rehype-hightlight-lines: private: true sandy: diff --git a/config/scripts.yaml b/config/scripts.yaml index 20e1df6b560..186d11b72d2 100644 --- a/config/scripts.yaml +++ b/config/scripts.yaml @@ -46,7 +46,7 @@ rehype-jargon: lint: "npx eslint 'src/*.mjs'" snapseries: lint: "npx eslint 'src/*.mjs'" -react-components: +react: lint: "eslint 'src/**/*.mjs'" # Sites go here diff --git a/config/software/packages.json b/config/software/packages.json index 06c041d81fe..1d2750f3463 100644 --- a/config/software/packages.json +++ b/config/software/packages.json @@ -3,7 +3,7 @@ "models": "Body measurements data for a range of default sizes", "new-design": "Initializer package for a new FreeSewing design: npx @freesewing/new-design", "prettier-config": "FreeSewing's shared configuration for prettier", - "react-components": "React components by/for FreeSewing", + "react": "React components, hooks and context by/for FreeSewing", "snapseries": "A series of common sizes for elastics and other series to be used with snapped percentage options", "rehype-jargon": "A Rehype plugin for jargon terms", "rehype-highlight-lines": "A Rehype plugin to add highlighted lines to code blocks" diff --git a/packages/react-components/CHANGELOG.md b/packages/react/CHANGELOG.md similarity index 64% rename from packages/react-components/CHANGELOG.md rename to packages/react/CHANGELOG.md index 169941b4ea5..80643c6ac6a 100644 --- a/packages/react-components/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,12 +1,6 @@ -# Change log for: @freesewing/react-components +# Change log for: @freesewing/react -## 3.2.0 (2024-02-11) - -### Added - - - This Pattern component now supports translation of nested arrays of strings, giving you more flexibility to concatenate translated parts of strings - ## 3.0.0 (2023-09-30) ### Changed diff --git a/packages/react-components/README.md b/packages/react/README.md similarity index 89% rename from packages/react-components/README.md rename to packages/react/README.md index 7dea16c88a5..64ed3fd1246 100644 --- a/packages/react-components/README.md +++ b/packages/react/README.md @@ -1,12 +1,12 @@

@freesewing/react-components on NPM + href="https://www.npmjs.com/package/@freesewing/react" + title="@freesewing/react on NPM" + >@freesewing/react on NPM License: MIT Code quality on DeepScan Open issues tagged pkg:react-components + href="https://github.com/freesewing/freesewing/issues?q=is%3Aissue+is%3Aopen+label%3Apkg%3Areact" + title="Open issues tagged pkg:react" + >Open issues tagged pkg:react

-# @freesewing/react-components +# @freesewing/react -React components by/for FreeSewing +React components, hooks and context by/for FreeSewing @@ -65,7 +65,7 @@ hardship, then you should [join us and become a patron](https://freesewing.org/c This repository is the FreeSewing *monorepo* holding all FreeSewing's websites, documentation, designs, plugins, and other NPM packages. -This folder holds: @freesewing/react-components +This folder holds: @freesewing/react If you're not entirely sure what to do or how to start, type this command: diff --git a/packages/react-components/build.mjs b/packages/react/build.mjs similarity index 100% rename from packages/react-components/build.mjs rename to packages/react/build.mjs diff --git a/packages/react/components/AuthWrapper/index.mjs b/packages/react/components/AuthWrapper/index.mjs new file mode 100644 index 00000000000..cd1fde7fdf5 --- /dev/null +++ b/packages/react/components/AuthWrapper/index.mjs @@ -0,0 +1,210 @@ +import Link from 'next/link' +import { useTranslation } from 'next-i18next' +import { useAccount } from 'shared/hooks/use-account.mjs' +import { useBackend } from 'shared/hooks/use-backend.mjs' +import { roles } from 'config/roles.mjs' +import { useEffect, useState } from 'react' +import { Loading } from 'shared/components/spinner.mjs' +import { horFlexClasses } from 'shared/utils.mjs' +import { LockIcon, PlusIcon } from 'shared/components/icons.mjs' +import { ConsentForm, ns as gdprNs } from 'shared/components/gdpr/form.mjs' + +export const ns = ['auth', gdprNs] + +const Wrap = ({ children }) => ( +
{children}
+) + +const ContactSupport = ({ t }) => ( +
+ + {t('contactSupport')} + +
+) + +const AuthRequired = ({ t, banner }) => ( + + {banner} +

{t('authRequired')}

+

{t('membersOnly')}

+
+ + + {t('signUp')} + + + + {t('signIn')} + +
+
+) + +const AccountInactive = ({ t, banner }) => ( + + {banner} +

{t('accountInactive')}

+

{t('accountInactiveMsg')}

+

{t('signupAgain')}

+
+ + {t('signUp')} + +
+
+) + +const AccountDisabled = ({ t, banner }) => ( + + {banner} +

{t('accountDisabled')}

+

{t('accountDisabledMsg')}

+ +
+) + +const AccountProhibited = ({ t, banner }) => ( + + {banner} +

{t('accountProhibited')}

+

{t('accountProhibitedMsg')}

+ +
+) + +const AccountStatusUnknown = ({ t, banner }) => ( + + {banner} +

{t('statusUnknown')}

+

{t('statusUnknownMsg')}

+ +
+) + +const RoleLacking = ({ t, requiredRole, role, banner }) => ( + + {banner} +

{t('roleLacking')}

+

+ + +) + +const ConsentLacking = ({ banner, refresh }) => { + const { setAccount, setToken, setSeenUser } = useAccount() + const backend = useBackend() + + const updateConsent = async ({ consent1, consent2 }) => { + let consent = 0 + if (consent1) consent = 1 + if (consent1 && consent2) consent = 2 + if (consent > 0) { + const result = await backend.updateConsent(consent) + console.log({ result }) + if (result.success) { + setToken(result.data.token) + setAccount(result.data.account) + setSeenUser(result.data.account.username) + refresh() + } else { + console.log('something went wrong', result) + refresh() + } + } + } + + return ( + +

+ {banner} + +
+
+ ) +} + +export const AuthWrapper = ({ children, requiredRole = 'user' }) => { + const { t } = useTranslation(ns) + const { account, setAccount, token, admin, stopImpersonating, signOut } = useAccount() + const backend = useBackend() + + const [ready, setReady] = useState(false) + const [impersonating, setImpersonating] = useState(false) + const [error, setError] = useState(false) + const [refreshCount, setRefreshCount] = useState(0) + + /* + * Avoid hydration errors + */ + useEffect(() => { + const verifyAdmin = async () => { + const result = await backend.adminPing(admin.token) + if (result.success && result.data.account.role === 'admin') { + setImpersonating({ + admin: result.data.account.username, + user: account.username, + }) + } + setReady(true) + } + const verifyUser = async () => { + const result = await backend.ping() + if (result.success) { + // Refresh account in local storage + setAccount({ + ...account, + ...result.data.account, + }) + } else { + if (result.data?.error?.error) setError(result.data.error.error) + else signOut() + } + setReady(true) + } + if (admin && admin.token) verifyAdmin() + if (token) verifyUser() + else setReady(true) + }, [admin, token, refreshCount, account, setAccount, backend, signOut]) + + const refresh = () => { + setRefreshCount(refreshCount + 1) + setError(false) + } + + if (!ready) + return ( + <> +

not ready

+ + + ) + + const banner = impersonating ? ( +
+ + Hi {impersonating.admin}, you are currently impersonating {impersonating.user} + + +
+ ) : null + + const childProps = { t, banner } + + if (!token || !account.username) return + if (error) { + if (error === 'accountInactive') return + if (error === 'accountDisabled') return + if (error === 'accountBlocked') return + if (error === 'consentLacking') return + return + } + + if (!roles.levels[account.role] || roles.levels[account.role] < roles.levels[requiredRole]) { + return + } + + return children +} diff --git a/packages/react/config/freesewing/index.mjs b/packages/react/config/freesewing/index.mjs new file mode 100644 index 00000000000..8234f581def --- /dev/null +++ b/packages/react/config/freesewing/index.mjs @@ -0,0 +1,170 @@ +/* + * This configuration file has the following named exports: + * + * account: Fields and control levels, and other account related settings + * backend: URL of the FreeSewing backend + * editor: Configuration for the pattern editor + * monorepo: URL of the FreeSewing monorepo + * social : Social media and other account links for FreeSewing + * controlLevels: Consolidated object holding all control levels + */ + +/* + * Structure of the various account fields and their control levels + */ +export const account = { + fields: { + data: { + bookmarks: 2, + sets: 1, + patterns: 1, + apikeys: 4, + }, + info: { + username: 2, + bio: 2, + img: 2, + email: 3, + }, + settings: { + language: 2, + units: 2, + newsletter: 2, + compare: 3, + control: 1, + consent: 2, + }, + security: { + password: 2, + mfa: 3, + apikeys: 4, + }, + identities: { + github: 3, + instagram: 3, + mastodon: 3, + reddit: 3, + twitch: 3, + tiktok: 3, + website: 3, + }, + }, + sets: { + name: 1, + img: 1, + public: 3, + units: 1, + notes: 2, + createdAt: 2, + updatedAt: 2, + id: 4, + }, + patterns: { + name: 1, + img: 1, + public: 3, + notes: 2, + createdAt: 2, + updatedAt: 2, + id: 4, + }, + statuses: { + 0: { + name: 'inactive', + color: 'neutral', + }, + 1: { + name: 'active', + color: 'success', + }, + '-1': { + name: 'paused', + color: 'warning', + }, + '-2': { + name: 'disabled', + color: 'error', + }, + }, +} + +/* + * URL of the FreeSewing backend + */ +export const backend = 'https://backend3.freesewing.org' + +/* + * The default control level in case we have nothing more specific + */ +export const defaultControlLevel = 3 + +/* + * Editor control levels + */ +export const editor = { + control: { + core: { + sa: 2, + paperless: 2, + locale: 3, + units: 1, + complete: 4, + expand: 4, + only: 4, + scale: 4, + margin: 4, + }, + ui: { + renderer: 4, + kiosk: 2, + }, + views: { + draft: 1, + measies: 1, + test: 3, + time: 3, + print: 1, + export: 1, + save: 1, + edit: 4, + logs: 2, + inspect: 4, + docs: 1, + }, + }, +} + +/* + * URL of the FreeSewing monorepo + */ +export const monorepo = 'https://github.com/freesewing/freesewing' + +/* + * Social media and other account links for FreeSewing + */ +export const social = { + YouTube: 'https://www.youtube.com/@freesewing', + Discord: 'https://discord.freesewing.org/', + Instagram: 'https://instagram.com/freesewing_org', + Facebook: 'https://www.facebook.com/groups/627769821272714/', + GitHub: 'https://github.com/freesewing', + Reddit: 'https://www.reddit.com/r/freesewing/', + Mastodon: 'https://freesewing.social/@freesewing', + Bluesky: 'https://bsky.app/profile/freesewing.org', +} + +/* + * Consolidated object holding all control levels + */ +export const controlLevels = { + ...account.fields.data, + ...account.fields.info, + ...account.fields.settings, + ...account.fields.security, + ...account.fields.identities, + sets: account.sets, + patterns: editor.account.patterns, + core: editor.control.core, + ui: editor.control.ui, + views: editor.control.views, +} diff --git a/packages/react/context/loadingStatus/index.mjs b/packages/react/context/loadingStatus/index.mjs new file mode 100644 index 00000000000..4ba3353bddc --- /dev/null +++ b/packages/react/context/loadingStatus/index.mjs @@ -0,0 +1,115 @@ +// __SDEFILE__ - This file is a dependency for the stand-alone environment +/* eslint-disable */ +// Not sure why but eslint does not seem to understand this file +// and I don't have time to hold its hand. +import { useState, useEffect, createContext } from 'react' +import { Spinner } from 'shared/components/spinner.mjs' +import { OkIcon, WarningIcon } from 'shared/components/icons.mjs' +import { useTranslation } from 'next-i18next' + +export const ns = ['status'] + +export const LoadingStatusContext = createContext([false]) + +/* + * Timeout in seconds before the loading status dissapears + */ +const timeout = 2 + +const LoadingStatus = ({ loadingStatus }) => { + const { t } = useTranslation(ns) + + const [fade, setFade] = useState('opacity-100') + const [timer, setTimer] = useState(false) + + useEffect(() => { + if (loadingStatus[2]) { + if (timer) clearTimeout(timer) + setTimer( + window.setTimeout(() => { + setFade('opacity-0') + }, timeout * 1000 - 350) + ) + } + }, [loadingStatus[2]]) + + if (!loadingStatus[0]) return null + + let color = 'secondary' + let icon = + if (loadingStatus[2]) { + color = loadingStatus[3] ? 'success' : 'error' + icon = loadingStatus[3] ? ( + + ) : ( + + ) + } + + return ( +
+
+ {icon} + {typeof loadingStatus[1] === 'object' && loadingStatus[1].props + ? loadingStatus[1] + : t(loadingStatus[1])} +
+
+ ) +} + +const LoadingProgress = ({ val = 0, max = 1, msg }) => ( +
+ {msg} + +
+) + +export const LoadingStatusContextProvider = ({ children }) => { + /* + * LoadingStatus should hold an array with 1 to 4 elements: + * 0 => Show loading status or not (true or false) + * 1 => Message to show + * 2 => Set this to true to make the loadingStatus dissapear after 2 seconds + * 3 => Set this to true to show success, false to show error (only when 2 is true) + */ + const [timer, setTimer] = useState(false) + + const [__loadingStatus, __setLoadingStatus] = useState({ + status: [false], + setLoadingStatus, + loading: false, + LoadingStatus: () => , + LoadingProgress, + }) + + useEffect(() => { + if (__loadingStatus.status[2]) { + if (timer) clearTimeout(timer) + setTimer( + window.setTimeout(() => { + setLoadingStatus([false]) + }, timeout * 1000) + ) + } + }, [__loadingStatus.status[2]]) + + function setLoadingStatus(newStatus) { + __setLoadingStatus({ + ...__loadingStatus, + status: newStatus, + loading: newStatus[0] || false, + LoadingStatus: () => , + }) + } + + return ( + + {children} + + ) +} diff --git a/packages/react-components/data.mjs b/packages/react/data.mjs similarity index 74% rename from packages/react-components/data.mjs rename to packages/react/data.mjs index 8d481e2a790..542ffd5ad5c 100644 --- a/packages/react-components/data.mjs +++ b/packages/react/data.mjs @@ -1,4 +1,4 @@ // This file is auto-generated | All changes you make will be overwritten. -export const name = '@freesewing/react-components' +export const name = '@freesewing/react' export const version = '3.3.0-rc.1' export const data = { name, version } diff --git a/packages/react/hooks/useAccount/index.mjs b/packages/react/hooks/useAccount/index.mjs new file mode 100644 index 00000000000..d8b3ae35406 --- /dev/null +++ b/packages/react/hooks/useAccount/index.mjs @@ -0,0 +1,102 @@ +import useLocalStorageState from 'use-local-storage-state' +import { defaultControlLevel } from '@freesewing/react-components/config/freesewing' + +/* + * When there is no account, we use this making it easy to check for username + * or control + */ +const noAccount = { username: false, control: defaultControlLevel } + +/* + * FreeSewing's useAccount hook. Grants access to the (data in the) user's account + */ +export function useAccount() { + /* + * Account is stored in persisted state (saved to local storage) + */ + const [account, setAccount] = useLocalStorageState('fs-account', { defaultValue: noAccount }) + + /* + * Admins are allowed to inpersonate a user. + * When that happens, we store the admin's account in this admin field (saved in local storage). + * When the admin ends the impersonation, we copy the account data under the admin key back into + * the regular account key. + * With this, admins would have to re-login after impersonating a user. + */ + const [admin, setAdmin] = useLocalStorageState('fs-admin', { defaultValue: noAccount }) + + /* + * This holds the JSON Web Token (JWT) returned from the backend after authentication + */ + const [token, setToken] = useLocalStorageState('fs-token', { defaultValue: null }) + + /* + * We use this to allow 'welcome back' style UI, asking for password, not username + */ + const [seenUser, setSeenUser] = useLocalStorageState('fs-seen-user', { defaultValue: false }) + + /* + * Clear user data when signing out + */ + const signOut = () => { + setAccount(noAccount) + setToken(null) + } + + /* + * Impersonate a user. + * Only admins can do this but that is enforced at the backend. + */ + const impersonate = (data) => { + /* + * Store token and account data in admin, so we can restore them later + */ + setAdmin({ token, account }) + + /* + * Create new account object based on the data passed in + */ + const newAccount = { + ...data.account, + impersonatingAdmin: { id: account.id, username: account.username }, + } + + /* + * Now set the new account and token + */ + setAccount(newAccount) + setToken(data.token) + } + + /* + * When impersonation ends, restore the original admin account + */ + const stopImpersonating = () => { + setAccount(admin.account) + setToken(admin.token) + clearAdmin() + } + + /* + * Don't keep account data lingering in the admin key + */ + const clearAdmin = () => setAdmin(noAccount) + + /* + * Return everything this hook provides + */ + return { + account, + setAccount, + token, + setToken, + seenUser, + setSeenUser, + signOut, + admin, + clearAdmin, + impersonate, + stopImpersonating, + control: account?.control || 2, + } +} diff --git a/packages/react/hooks/useBackend/index.mjs b/packages/react/hooks/useBackend/index.mjs new file mode 100644 index 00000000000..8d181a416bc --- /dev/null +++ b/packages/react/hooks/useBackend/index.mjs @@ -0,0 +1,814 @@ +import { useMemo } from 'react' +import { backend } from '@freesewing/react-components/config/freesewing' +import { RestClient } from '@freesewing/react-components/lib/restClient' +import { useAccount } from '@freesewing/react-components/hooks/useAccount' + +/** + * The useBackend hook + * + * This hook provides access to the FreeSewing backend + */ +export function useBackend() { + /* + * Load the token via the useAccount hook + */ + const { token } = useAccount() + + /* + * Memoize this call for efficiency + */ + const backend = useMemo(() => new Backend(token), [token]) + + /* + * This backend object rovides the following methods: + * + * - backend.adminSearchUsers + * - backend.adminLoadUser + * - backend.adminUpdateUser + * - backend.adminImpersonateUser + * - backend.adminLoadSubscribers + * - backend.adminPing + * - backend.acceptCset + * - backend.confirmMfa + * - backend.confirmSignup + * - backend.createApikey + * - backend.createBookmark + * - backend.createSocialImage + * - backend.createDiscussion + * - backend.createIssue + * - backend.createPattern + * - backend.createPostPr + * - backend.createSet + * - backend.disableMfa + * - backend.enableMfa + * - backend.exportAccount + * - backend.getApikey + * - backend.getApikeys + * - backend.getBookmark + * - backend.getBookmarks + * - backend.getConfirmation + * - backend.getCuratedSet + * - backend.getCuratedSets + * - backend.getPattern + * - backend.getPatterns + * - backend.getPublicPattern + * - backend.getPublicSet + * - backend.getSet + * - backend.getSets + * - backend.getStats + * - backend.getSuggestedPacks + * - backend.getSuggestedSets + * - backend.getUserCount + * - backend.getUserData + * - backend.getUserProfile + * - backend.isPostSlugAvailable + * - backend.isUsernameAvailable + * - backend.newsletterConfirmSubscribe + * - backend.newsletterSubscribe + * - backend.newsletterUnsubscribe + * - backend.oauthInit + * - backend.oauthSignIn + * - backend.ping + * - backend.reloadAccount + * - backend.removeAccount + * - backend.removeApikey + * - backend.removeBookmark + * - backend.removeCuratedSet + * - backend.removeImage + * - backend.removePattern + * - backend.removeSet + * - backend.removeSuggestedSet + * - backend.restrictAccount + * - backend.signIn + * - backend.signInFromLink + * - backend.signUp + * - backend.suggestCset + * - backend.suggestOpack + * - backend.updateAccount + * - backend.updateCuratedSet + * - backend.updateConsent + * - backend.updatePattern + * - backend.updateSet + * - backend.uploadImage + * - backend.uploadImageAnon + */ + return backend +} + +/** + * This helper function creates the authentication headers + * + * @param {string} token - The JSON Web Token to authenticate to the backend + * @return {object} headers - An object holding headers for the REST API call + */ +function authenticationHeaders(token) { + return token + ? { + headers: { Authorization: 'Bearer ' + token }, + } + : { headers: {} } +} + +/** + * This creates a backend instance and stores the authentication data + * + * @param {string} token - The JWT token to use for authentication to the backend + */ +function Backend(token) { + this.token = token + this.headers = authenticationHeaders(token) + this.restClient = new RestClient(backend, this.headers) + this.get = this.restClient.get + this.put = this.restClient.put + this.post = this.restClient.post +} + +/** + * Admin: Search user + * + * @param {string} q - The search query + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.adminSearchUsers = async function (q) { + return await this.post('/admin/search/users/jwt', { q }) +} + +/* + * Admin: Load user + * + * @param {number} id - The user ID to load + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.adminLoadUser = async function (id) { + return await this.get(`/admin/user/${id}/jwt`) +} + +/** + * Admin: Update user + * + * @param {object} data + * @param {number} data.id - The user ID to update + * @param {object} data.data - The data for the API request + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.adminUpdateUser = async function ({ id, data }) { + return await this.patch(`/admin/user/${id}/jwt`, data) +} + +/** + * Admin: Impersonate user + * + * @param {number} id - The user ID to impersonate + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.adminImpersonateUser = async function (id) { + return await this.get(`/admin/impersonate/${id}/jwt`) +} + +/* + * Load newsletter subscribers (admin method) + */ +Backend.prototype.adminLoadSubscribers = async function () { + return await this.get(`/admin/subscribers/jwt`) +} + +/* + * Verify an admin account while impersonating another user + */ +Backend.prototype.adminPing = async function (token) { + return await this.get(`/whoami/jwt`, { Authorization: `Bearer: ${token}` }) +} +/* + * Create a curated set from a suggested measurements set + */ +Backend.prototype.acceptCset = async function (id) { + return await this.post(`/curated-sets/from/${id}/jwt`) +} + +/* + * Confirm MFA + * + * @param {object} data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.confirmMfa = async function (data) { + return await this.post(`/account/mfa/jwt`, { ...data, mfa: true }) +} + +/* + * Confirm a signup + * + * @param {object} data + * @param {string} data.id - The confirmation ID + * @param {string} data.consent - The consent data + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.confirmSignup = async function ({ id, consent }) { + return await this.post(`/confirm/signup/${id}`, { consent }) +} + +/** + * Create API key + * + * @param {object} data - The data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.createApikey = async function (data) { + return await this.post(`/apikeys/jwt`, data) +} + +/** + * Create bookmark + * + * @param {object} data - Data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.createBookmark = async function (data) { + return await this.post(`/bookmarks/jwt`, data) +} + +/** + * Generate a social media image + * + * @param {object} data - Data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.createSocialImage = async function (data) { + return await this.post('/img', data) +} + +/** + * Create GitHub discussion + * + * @param {object} data - Data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.createDiscussion = async function (data) { + return await this.post(`/discussions`, data) +} + +/** + * Create GitHub issue + * + * @param {object} data - Data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.createIssue = async function (data) { + return await this.post(`/issues`, data) +} + +/** + * Create pattern + * + * @param {object} data - Data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.createPattern = async function (data) { + return await this.post(`/patterns/jwt`, data) +} + +/** + * Create a pull request for a showcase or blog post + * + * @param {object} data - Data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.createPostPr = async function (type, data) { + return await this.post(`/flows/pr/${type}/jwt`, data) +} + +/** + * Create measurements set + * + * @param {object} data - Data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.createSet = async function (data) { + return await this.post(`/sets/jwt`, data) +} + +/** + * Disable MFA for the current user + * + * @param {object} data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.disableMfa = async function (data) { + return await this.post(`/account/mfa/jwt`, { ...data, mfa: false }) +} + +/** + * Enable MFA for the current user + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.enableMfa = async function () { + return await this.post(`/account/mfa/jwt`, { mfa: true }) +} + +/** + * Export account data for the current user + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.exportAccount = async function () { + return await this.get(`/account/export/jwt`) +} + +/** + * Get API key + * + * @param {string} id - The API Key ID + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getApikey = async function (id) { + return await this.get(`/apikeys/${id}/jwt`) +} + +/** + * Get API keys for the current user + */ +Backend.prototype.getApikeys = async function () { + return await this.get(`/apikeys/jwt`) +} + +/** + * Get bookmark + * + * @param {string} id - The bookmark ID + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getBookmark = async function (id) { + return await this.get(`/bookmarks/${id}/jwt`) +} + +/** + * Get bookmarks (for the current user) + */ +Backend.prototype.getBookmarks = async function () { + return await this.get(`/bookmarks/jwt`) +} + +/** + * Get data for a confirmation + * + * @param {object} data + * @param {string} data.id - The confirmation ID + * @param {string} data.check - The confirmation check value + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getConfirmation = async function ({ id, check }) { + return await this.get(`/confirmations/${id}/${check}`) +} + +/** + * Get curated measurements set + * + * @param {number} id - The curated measurements set ID + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getCuratedSet = async function (id) { + return await this.get(`/curated-sets/${id}`) +} + +/** + * Get curated measurements sets + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getCuratedSets = async function () { + return await this.get(`/curated-sets`) +} + +/** + * Get pattern + * + * @param {number} id - The pattern ID + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getPattern = async function (id) { + return await this.get(`/patterns/${id}/jwt`) +} + +/** + * Get patterns for the current user + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getPatterns = async function () { + return await this.get(`/patterns/jwt`) +} + +/** + * Get public pattern + * + * @param {number} id - The pattern ID + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getPublicPattern = async function (id) { + return await this.get(`/patterns/${id}.json`) +} + +/** + * Get public measurements set + * + * @param {number} id - The public measurements set ID + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getPublicSet = async function (id) { + return await this.get(`/sets/${id}.json`) +} + +/** + * Get measurements set + * + * @param {number} id - The measurements set ID + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getSet = async function (id) { + return await this.get(`/sets/${id}/jwt`) +} + +/* + * Get measurements sets for the current user + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getSets = async function () { + return await this.get(`/sets/jwt`) +} + +/* + * Get stats (info about how many users, patterns, and so on) + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getStats = async function () { + return await this.get(`/info/stats`) +} + +/* + * Get option packs suggested for curation + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getSuggestedPacks = async function () { + return await this.get(`/suggested-packs/jwt`) +} + +/** + * Get measurements sets suggested for curation + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getSuggestedSets = async function () { + return await this.get(`/suggested-sets/jwt`) +} + +/** + * Get user count (how many users FreeSewing has) + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getUserCount = async function () { + return await this.get(`/info/users`) +} + +/** + * Get user data + * + * @param {number} uid - The user ID + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getUserData = async function (uid) { + return await this.get(`/users/${uid}/jwt`) +} + +/** + * Get user profile + * + * @param {number} uid - The user ID + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.getUserProfile = async function (uid) { + return await this.get(`/users/${uid}`) +} + +/* + * Check whether a slug for a blog or showcase post is available + * + * @param {object} data + * @param {string} data.slug - The slug to check + * @param {string} data.type - One of 'blog' or 'showcase' + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.isPostSlugAvailable = async function ({ slug, type }) { + const response = await this.get(`/slugs/${type}/${slug}/jwt`, this.auth) + + // 404 means username is available, which is success in this case + return response[0] === 404 + ? { success: true, data: false, available: true, response } + : { success: false, available: false, response } +} + +/** + * Checks whether a username is available + * + * @param {string} username - The username to check + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.isUsernameAvailable = async function (username) { + const response = await this.post(`/available/username/jwt`, { username }) + + /* + * Status 404 means username is available, which is success in this case + */ + return response[0] === 404 + ? { success: true, data: false, available: true, response } + : { success: false, available: false, response } +} + +/** +/* + * Confirm newsletter subscribe + * + * @param {object} data + * @param {string} data.id - The confirmation ID + * @param {string} data.ehash - The ehash value + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.newsletterConfirmSubscribe = async function ({ id, ehash }) { + return await this.put('/subscriber', { id, ehash }) +} + +/** + * Subscribe to newsletter + * + * @param {string} email - The email to subscribe + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.newsletterSubscribe = async function (email) { + return await this.post('/subscriber', { email, language: 'en' }) +} + +/* + * Newsletter unsubscribe + * + * @param {string} ehash - The ehash to unsubscribe + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.newsletterUnsubscribe = async function (ehash) { + return await this.delete(`/subscriber/${ehash}`) +} + +/* + * Init Oauth flow for oauth provider + * + * @param {object} data + * @param {string} data.provider - ID of the OAuth provider + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.oauthInit = async function (provider) { + return await this.post('/signin/oauth/init', { provider }) +} + +/* + * User sign in via oauth provider + * + * @param {object} data + * @param {string} data.state - The Oath state + * @param {code} data.code - The OAuth code + * @param {string} data.provider - ID of the OAuth provider + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.oauthSignIn = async function ({ state, code, provider }) { + return await this.post('/signin/oauth', { state, code, provider }) +} + +/** + * Ping backend to see if current token is still valid + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.ping = async function () { + return await this.get(`/whoami/jwt`) +} + +/** + * Reload account - Useful for when local state gets out of sync + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.reloadAccount = async function () { + return await this.get(`/whoami/jwt`) +} + +/** + * Remove account (the current logged in user) + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.removeAccount = async function () { + return await this.delete(`/account/jwt`) +} + +/** + * Remove API key + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.removeApikey = async function (id) { + return await this.delete(`/apikeys/${id}/jwt`, this.auth) +} + +/* + * Remove bookmark + * + * @param {string} id - The bookmark ID + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.removeBookmark = async function (id) { + return await this.delete(`/bookmarks/${id}/jwt`) +} + +/** + * Remove curated measurements set + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.removeCuratedSet = async function (id) { + return await this.delete(`/curated-sets/${id}/jwt`) +} + +/** + * Remove an uploaded image + * + * @param {string} id - The image ID + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.removeImage = async function (id) { + return await this.delete(`/images/${id}/jwt`) +} + +/** + * Remove pattern + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.removePattern = async function (id) { + return await this.delete(`/patterns/${id}/jwt`, this.auth) +} + +/** + * Remove measurements set + * + * @param {string} id - The measurements set ID + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.removeSet = async function (id) { + return await this.delete(`/sets/${id}/jwt`) +} + +/* + * Remove suggested measurements set + */ +Backend.prototype.removeSuggestedSet = async function (id) { + return await this.delete(`/suggested-sets/${id}/jwt`) +} + +/** + * Restrict processing of account data + * + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.restrictAccount = async function () { + return await this.get(`/account/restrict/jwt`) +} + +/** + * User signin/login + * + * @param {object} data + * @param {string} data.username - The account username + * @param {string} data.password - The account password + * @param {string} data.token - The (optional) MFA token + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.signIn = async function ({ username, password = false, token = false }) { + return password === false + ? await this.post('/signinlink', { username }) + : await this.post('/signin', { username, password, token }) +} + +/** + * Trade in sign-in link id & check for JWT token + * + * @param {object} data + * @param {string} data.id - The confirmation ID + * @param {string} data.check - The confirmation check value + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.signInFromLink = async function ({ id, check }) { + return await this.post(`/signinlink/${id}/${check}`) +} + +/** + * User signup + * + * @param {object} data + * @param {string} data.email - The Email address to sign up + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.signUp = async function ({ email }) { + return await this.post('/signup', { email }) +} + +/* + * Suggest a measurements set for curation + * + * @param {object} data - Data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.suggestCset = async function (data) { + return await this.post(`/curated-sets/suggest/jwt`, data) +} + +/* + * Suggest an option pack for curation + * + * @param {object} data - Data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.suggestOpack = async function (data) { + return await this.post(`/option-packs/suggest/jwt`, data) +} + +/** + * Generic update account method + * + * @param {object} data - Data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.updateAccount = async function (data) { + return await this.patch(`/account/jwt`, data) +} + +/** + * Generic update curated measurements set method + * + * @param {object} consent + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.updateCuratedSet = async function (id, data) { + return await this.patch(`/curated-sets/${id}/jwt`, data) +} + +/** + * Update consent (uses the jwt-guest middleware) + * + * @param {object} consent + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.updateConsent = async function (consent) { + return await this.patch(`/consent/jwt`, { consent }) +} + +/** + * Generic update pattern set method + * + * @param {object} data - Data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.updatePattern = async function (id, data) { + return await this.patch(`/patterns/${id}/jwt`, data) +} + +/** + * Generic update measurements set method + * + * @param {object} data - Data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.updateSet = async function (id, data) { + return await this.patch(`/sets/${id}/jwt`, data) +} + +/** + * Upload an image + * + * @param {object} data - Data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.uploadImage = async function (data) { + return await this.post('/images/jwt', data) +} + +/** + * Upload an image anonymously + * + * @param {object} data - Data for the API call + * @return {array} result - The REST response, a [status, data] array + */ +Backend.prototype.uploadImageAnon = async function (data) { + return await this.post('/images', data) +} diff --git a/packages/react/lib/RestClient/index.mjs b/packages/react/lib/RestClient/index.mjs new file mode 100644 index 00000000000..5ec41c80120 --- /dev/null +++ b/packages/react/lib/RestClient/index.mjs @@ -0,0 +1,120 @@ +/** + * A simple HTTP REST client + * + * We use this in the useBackend hook, but it's also possible to use this with + * any other REST API. + * This uses the fetch API, so it has no dependencies. + * However, that means you cannot use this with a REST API using a non-trusted X.509 certificate, since fetch does not provide an escape hatch for that. + * If that's your use-case, use Axios instead. + * + * @param {string} baseUrl - The base URL of the API that will be used as a prefix for all calls + * @param {string} baseHeaders - Any headers to add to each request. Eg for authentication + * @return {object} client - An object with get, post, and put methods + */ +export function RestClient(baseUrl = '', baseHeaders = {}) { + this.baseUrl = baseUrl + this.baseHeaders = baseHeaders + + this.delete = async function (url, headers, raw, log) { + return withoutBody('DELETE', baseUrl + url, { ...baseHeaders, ...headers }, raw, log) + } + + this.get = async function (url, headers, raw, log) { + return withoutBody('GET', baseUrl + url, { ...baseHeaders, ...headers }, raw, log) + } + + this.head = async function (url, headers, raw, log) { + return withoutBody('HEAD', baseUrl + url, { ...baseHeaders, ...headers }, raw, log) + } + + this.post = async function (url, data, headers, raw, log) { + return withBody('POST', baseUrl + url, data, { ...baseHeaders, ...headers }, raw, log) + } + + this.put = async function (url, data, headers, raw, log) { + return withBody('PUT', baseUrl + url, data, { ...baseHeaders, headers }, raw, log) + } + + return this +} + +/* + * General purpose method to call a REST API without a body (eg: GET or DELETE requests) + * + * @param {string} url - The URL to call + * @param {object} headers - Any request headers to add + * @param {bool} raw - Set this to something truthy to not parse the result as JSON + * @param {function} log - Optional custom logging method to log errors + * @return {response} array - An array with status code followed by either the result parse as JSON, the raw result, or false in case of trouble + */ +async function withoutBody(method = 'GET', url, headers = {}, raw = false, log = console.log) { + let response + try { + response = await fetch(url, { method, headers }) + } catch (err) { + if (log) console.log({ url, err }) + } + + if (!response) return [false, false] + + /* + * Can we parse the response as JSON? + */ + let body + try { + body = raw ? await response.text() : await response.json() + } catch (err) { + try { + body = await response.text() + } catch (err) { + body = false + } + } + + return [response.status || false, body] +} + +/* + * General purpose method to call a REST API with a body (eg: PATCH, PUT, or POST requests) + * + * @param {url} string - The URL to call + * @param {data} string - The data to send + * @param {object} headers - Any request headers to add + * @param {raw} string - Set this to something truthy to not parse the result as JSON + * @param {function} log - Optional logging method to log errors + * @return {response} array - An array with status code followed by either the result parse as JSON, the raw result, or false in case of trouble + */ +async function withBody(method = 'POST', url, data, headers, raw = false, log = console.log) { + const request = { method, headers } + if (data && typeof data === 'object' && Object.keys(data).length > 0) { + request.body = JSON.stringify(data) + request.headers['Content-Type'] = 'application/json' + } + + let response + try { + response = await fetch(url, request) + } catch (err) { + if (log) log(err) + } + + /* + * Some status codes have no response body + */ + if (response?.status && [204].includes(response.status)) return [response.status, {}] + else if (response?.status && response.status < 400) { + let data + try { + data = raw ? await response.text() : await response.json() + } catch (err) { + if (log) log(err) + return raw ? [response.status, { err }] : [response.status, data] + } + return [response.status, data] + } + + /* + * If we end up here, status code is 400 or higher so it's an error + */ + return [response?.status || 500, false] +} diff --git a/packages/react-components/package.json b/packages/react/package.json similarity index 61% rename from packages/react-components/package.json rename to packages/react/package.json index e5fc181909f..5d3bbe93b07 100644 --- a/packages/react-components/package.json +++ b/packages/react/package.json @@ -1,7 +1,7 @@ { - "name": "@freesewing/react-components", + "name": "@freesewing/react", "version": "3.3.0-rc.1", - "description": "React components by/for FreeSewing", + "description": "React components, hooks and context by/for FreeSewing", "author": "Joost De Cock (https://github.com/joostdecock)", "homepage": "https://freesewing.org/", "repository": "github:freesewing/freesewing", @@ -26,21 +26,15 @@ }, "./linedrawings": "./src/linedrawings/index.mjs", "./pattern": "./src/pattern/index.mjs", - "./xray": "./src/pattern-xray/index.mjs" + "./xray": "./src/pattern-xray/index.mjs", + "./config/freesewing": "./config/freesewing/index.mjs", + "./context/loadingStatus": "./context/loadingStatus/index.mjs", + "./hooks/useBackend": "./hooks/useBackend/index.mjs", + "./lib/RestClient": "./lib/RestClient/index.mjs" }, "scripts": { - "build": "node build.mjs", - "build:all": "yarn build", - "clean": "rimraf dist", - "mbuild": "NO_MINIFY=1 node build.mjs", - "symlink": "mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -", - "test": "echo \"react-components: No tests configured. Perhaps you could write some?\" && exit 0", - "vbuild": "VERBOSE=1 node build.mjs", - "lab": "cd ../../sites/lab && yarn start", - "tips": "node ../../scripts/help.mjs", - "lint": "eslint 'src/**/*.mjs'", - "wbuild": "node build.mjs", - "wbuild:all": "yarn wbuild" + "lint": "eslint 'components/**/*.mjs' 'hooks/**/*.mjs' 'lib/**/*.mjs' 'context/**/*.mjs' 'config/**/*.mjs'", + "prettier": "npx prettier --write 'components/**/*.mjs' 'hooks/**/*.mjs' 'lib/**/*.mjs' 'context/**/*.mjs' 'config/**/*.mjs'" }, "peerDependencies": { "react": "^18.2.0" @@ -55,7 +49,9 @@ }, "devDependencies": {}, "files": [ - "dist/*", + "components/**", + "hooks/**", + "lib/**", "README.md" ], "publishConfig": { diff --git a/packages/react-components/src/editor/components/view-wrapper.mjs b/packages/react/src/editor/components/view-wrapper.mjs similarity index 100% rename from packages/react-components/src/editor/components/view-wrapper.mjs rename to packages/react/src/editor/components/view-wrapper.mjs diff --git a/packages/react-components/src/editor/en.yaml b/packages/react/src/editor/en.yaml similarity index 100% rename from packages/react-components/src/editor/en.yaml rename to packages/react/src/editor/en.yaml diff --git a/packages/react-components/src/editor/index.mjs b/packages/react/src/editor/index.mjs similarity index 100% rename from packages/react-components/src/editor/index.mjs rename to packages/react/src/editor/index.mjs diff --git a/packages/react-components/src/editor/nl.yaml b/packages/react/src/editor/nl.yaml similarity index 100% rename from packages/react-components/src/editor/nl.yaml rename to packages/react/src/editor/nl.yaml diff --git a/packages/react-components/src/editor/props.md b/packages/react/src/editor/props.md similarity index 100% rename from packages/react-components/src/editor/props.md rename to packages/react/src/editor/props.md diff --git a/packages/react-components/src/editor/swizzle/components/accordion.mjs b/packages/react/src/editor/swizzle/components/accordion.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/accordion.mjs rename to packages/react/src/editor/swizzle/components/accordion.mjs diff --git a/packages/react-components/src/editor/swizzle/components/aside-view-menu.mjs b/packages/react/src/editor/swizzle/components/aside-view-menu.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/aside-view-menu.mjs rename to packages/react/src/editor/swizzle/components/aside-view-menu.mjs diff --git a/packages/react-components/src/editor/swizzle/components/auth-wrapper.mjs b/packages/react/src/editor/swizzle/components/auth-wrapper.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/auth-wrapper.mjs rename to packages/react/src/editor/swizzle/components/auth-wrapper.mjs diff --git a/packages/react-components/src/editor/swizzle/components/curated-sets.mjs b/packages/react/src/editor/swizzle/components/curated-sets.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/curated-sets.mjs rename to packages/react/src/editor/swizzle/components/curated-sets.mjs diff --git a/packages/react-components/src/editor/swizzle/components/designs-view.mjs b/packages/react/src/editor/swizzle/components/designs-view.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/designs-view.mjs rename to packages/react/src/editor/swizzle/components/designs-view.mjs diff --git a/packages/react-components/src/editor/swizzle/components/draft-view.mjs b/packages/react/src/editor/swizzle/components/draft-view.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/draft-view.mjs rename to packages/react/src/editor/swizzle/components/draft-view.mjs diff --git a/packages/react-components/src/editor/swizzle/components/dynamic-mdx.mjs b/packages/react/src/editor/swizzle/components/dynamic-mdx.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/dynamic-mdx.mjs rename to packages/react/src/editor/swizzle/components/dynamic-mdx.mjs diff --git a/packages/react-components/src/editor/swizzle/components/error-view.mjs b/packages/react/src/editor/swizzle/components/error-view.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/error-view.mjs rename to packages/react/src/editor/swizzle/components/error-view.mjs diff --git a/packages/react-components/src/editor/swizzle/components/flags.mjs b/packages/react/src/editor/swizzle/components/flags.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/flags.mjs rename to packages/react/src/editor/swizzle/components/flags.mjs diff --git a/packages/react-components/src/editor/swizzle/components/header-menu.mjs b/packages/react/src/editor/swizzle/components/header-menu.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/header-menu.mjs rename to packages/react/src/editor/swizzle/components/header-menu.mjs diff --git a/packages/react-components/src/editor/swizzle/components/html-span.mjs b/packages/react/src/editor/swizzle/components/html-span.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/html-span.mjs rename to packages/react/src/editor/swizzle/components/html-span.mjs diff --git a/packages/react-components/src/editor/swizzle/components/icons.mjs b/packages/react/src/editor/swizzle/components/icons.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/icons.mjs rename to packages/react/src/editor/swizzle/components/icons.mjs diff --git a/packages/react-components/src/editor/swizzle/components/index.mjs b/packages/react/src/editor/swizzle/components/index.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/index.mjs rename to packages/react/src/editor/swizzle/components/index.mjs diff --git a/packages/react-components/src/editor/swizzle/components/inputs.mjs b/packages/react/src/editor/swizzle/components/inputs.mjs similarity index 99% rename from packages/react-components/src/editor/swizzle/components/inputs.mjs rename to packages/react/src/editor/swizzle/components/inputs.mjs index 9fa1b579575..b2386702e9a 100644 --- a/packages/react-components/src/editor/swizzle/components/inputs.mjs +++ b/packages/react/src/editor/swizzle/components/inputs.mjs @@ -247,8 +247,8 @@ export const MeasurementInput = ({ typeof original === 'undefined' ? original : isDegree - ? Number(original) - : Swizzled.methods.measurementAsUnits(original, units) + ? Number(original) + : Swizzled.methods.measurementAsUnits(original, units) ) const [validatedVal, setValidatedVal] = useState( Swizzled.methods.measurementAsUnits(original, units) diff --git a/packages/react-components/src/editor/swizzle/components/large-screen-only.mjs b/packages/react/src/editor/swizzle/components/large-screen-only.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/large-screen-only.mjs rename to packages/react/src/editor/swizzle/components/large-screen-only.mjs diff --git a/packages/react-components/src/editor/swizzle/components/link.mjs b/packages/react/src/editor/swizzle/components/link.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/link.mjs rename to packages/react/src/editor/swizzle/components/link.mjs diff --git a/packages/react-components/src/editor/swizzle/components/loaders.mjs b/packages/react/src/editor/swizzle/components/loaders.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/loaders.mjs rename to packages/react/src/editor/swizzle/components/loaders.mjs diff --git a/packages/react-components/src/editor/swizzle/components/loading-status.mjs b/packages/react/src/editor/swizzle/components/loading-status.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/loading-status.mjs rename to packages/react/src/editor/swizzle/components/loading-status.mjs diff --git a/packages/react-components/src/editor/swizzle/components/markdown.mjs b/packages/react/src/editor/swizzle/components/markdown.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/markdown.mjs rename to packages/react/src/editor/swizzle/components/markdown.mjs diff --git a/packages/react-components/src/editor/swizzle/components/measurements-editor.mjs b/packages/react/src/editor/swizzle/components/measurements-editor.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/measurements-editor.mjs rename to packages/react/src/editor/swizzle/components/measurements-editor.mjs diff --git a/packages/react-components/src/editor/swizzle/components/measurements-set-card.mjs b/packages/react/src/editor/swizzle/components/measurements-set-card.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/measurements-set-card.mjs rename to packages/react/src/editor/swizzle/components/measurements-set-card.mjs diff --git a/packages/react-components/src/editor/swizzle/components/measurements-view.mjs b/packages/react/src/editor/swizzle/components/measurements-view.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/measurements-view.mjs rename to packages/react/src/editor/swizzle/components/measurements-view.mjs diff --git a/packages/react-components/src/editor/swizzle/components/menus/containers.mjs b/packages/react/src/editor/swizzle/components/menus/containers.mjs similarity index 96% rename from packages/react-components/src/editor/swizzle/components/menus/containers.mjs rename to packages/react/src/editor/swizzle/components/menus/containers.mjs index 9ee30172276..2e70986c884 100644 --- a/packages/react-components/src/editor/swizzle/components/menus/containers.mjs +++ b/packages/react/src/editor/swizzle/components/menus/containers.mjs @@ -164,10 +164,10 @@ export const MenuItemGroup = ({ const ItemIcon = item.icon ? item.icon : item.isGroup - ? Swizzled.components.GroupIcon - : Icon - ? Icon - : () => fixme-icon + ? Swizzled.components.GroupIcon + : Icon + ? Icon + : () => fixme-icon const Value = item.isGroup ? () => (
@@ -176,10 +176,10 @@ export const MenuItemGroup = ({
) : isDesignOptionsGroup - ? values[Swizzled.methods.designOptionType(item)] - : values[itemName] - ? values[itemName] - : () => ¯\_(ツ)_/¯ + ? values[Swizzled.methods.designOptionType(item)] + : values[itemName] + ? values[itemName] + : () => ¯\_(ツ)_/¯ return [
diff --git a/packages/react-components/src/editor/swizzle/components/menus/core-settings-menu.mjs b/packages/react/src/editor/swizzle/components/menus/core-settings-menu.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/menus/core-settings-menu.mjs rename to packages/react/src/editor/swizzle/components/menus/core-settings-menu.mjs diff --git a/packages/react-components/src/editor/swizzle/components/menus/design-options-menu.mjs b/packages/react/src/editor/swizzle/components/menus/design-options-menu.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/menus/design-options-menu.mjs rename to packages/react/src/editor/swizzle/components/menus/design-options-menu.mjs diff --git a/packages/react-components/src/editor/swizzle/components/menus/draft-menu.mjs b/packages/react/src/editor/swizzle/components/menus/draft-menu.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/menus/draft-menu.mjs rename to packages/react/src/editor/swizzle/components/menus/draft-menu.mjs diff --git a/packages/react-components/src/editor/swizzle/components/menus/shared-inputs.mjs b/packages/react/src/editor/swizzle/components/menus/shared-inputs.mjs similarity index 99% rename from packages/react-components/src/editor/swizzle/components/menus/shared-inputs.mjs rename to packages/react/src/editor/swizzle/components/menus/shared-inputs.mjs index c2cb878fa05..283c34e721c 100644 --- a/packages/react-components/src/editor/swizzle/components/menus/shared-inputs.mjs +++ b/packages/react/src/editor/swizzle/components/menus/shared-inputs.mjs @@ -80,8 +80,8 @@ export const MenuListInput = ({ const titleKey = config.choiceTitles ? config.choiceTitles[entry] : isDesignOption - ? `${design}:${name}.${entry}` - : `${name}.o.${entry}` + ? `${design}:${name}.${entry}` + : `${name}.o.${entry}` const title = config.titleMethod ? config.titleMethod(entry, t) : t(`${titleKey}.t`) const desc = config.valueMethod ? config.valueMethod(entry, t) : t(`${titleKey}.d`) const sideBySide = config.sideBySide || desc.length + title.length < 42 diff --git a/packages/react-components/src/editor/swizzle/components/menus/shared-values.mjs b/packages/react/src/editor/swizzle/components/menus/shared-values.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/menus/shared-values.mjs rename to packages/react/src/editor/swizzle/components/menus/shared-values.mjs diff --git a/packages/react-components/src/editor/swizzle/components/menus/ui-preferences-menu.mjs b/packages/react/src/editor/swizzle/components/menus/ui-preferences-menu.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/menus/ui-preferences-menu.mjs rename to packages/react/src/editor/swizzle/components/menus/ui-preferences-menu.mjs diff --git a/packages/react-components/src/editor/swizzle/components/null.mjs b/packages/react/src/editor/swizzle/components/null.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/null.mjs rename to packages/react/src/editor/swizzle/components/null.mjs diff --git a/packages/react-components/src/editor/swizzle/components/pattern-layout.mjs b/packages/react/src/editor/swizzle/components/pattern-layout.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/pattern-layout.mjs rename to packages/react/src/editor/swizzle/components/pattern-layout.mjs diff --git a/packages/react-components/src/editor/swizzle/components/popout.mjs b/packages/react/src/editor/swizzle/components/popout.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/popout.mjs rename to packages/react/src/editor/swizzle/components/popout.mjs diff --git a/packages/react-components/src/editor/swizzle/components/save-view.mjs b/packages/react/src/editor/swizzle/components/save-view.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/save-view.mjs rename to packages/react/src/editor/swizzle/components/save-view.mjs diff --git a/packages/react-components/src/editor/swizzle/components/sets.mjs b/packages/react/src/editor/swizzle/components/sets.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/sets.mjs rename to packages/react/src/editor/swizzle/components/sets.mjs diff --git a/packages/react-components/src/editor/swizzle/components/spinner.mjs b/packages/react/src/editor/swizzle/components/spinner.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/spinner.mjs rename to packages/react/src/editor/swizzle/components/spinner.mjs diff --git a/packages/react-components/src/editor/swizzle/components/tabs.mjs b/packages/react/src/editor/swizzle/components/tabs.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/tabs.mjs rename to packages/react/src/editor/swizzle/components/tabs.mjs diff --git a/packages/react-components/src/editor/swizzle/components/tooltip.mjs b/packages/react/src/editor/swizzle/components/tooltip.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/tooltip.mjs rename to packages/react/src/editor/swizzle/components/tooltip.mjs diff --git a/packages/react-components/src/editor/swizzle/components/undos-view.mjs b/packages/react/src/editor/swizzle/components/undos-view.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/undos-view.mjs rename to packages/react/src/editor/swizzle/components/undos-view.mjs diff --git a/packages/react-components/src/editor/swizzle/components/ux.mjs b/packages/react/src/editor/swizzle/components/ux.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/ux.mjs rename to packages/react/src/editor/swizzle/components/ux.mjs diff --git a/packages/react-components/src/editor/swizzle/components/view-picker.mjs b/packages/react/src/editor/swizzle/components/view-picker.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/view-picker.mjs rename to packages/react/src/editor/swizzle/components/view-picker.mjs diff --git a/packages/react-components/src/editor/swizzle/components/zoomable-pattern.mjs b/packages/react/src/editor/swizzle/components/zoomable-pattern.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/components/zoomable-pattern.mjs rename to packages/react/src/editor/swizzle/components/zoomable-pattern.mjs diff --git a/packages/react-components/src/editor/swizzle/config.mjs b/packages/react/src/editor/swizzle/config.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/config.mjs rename to packages/react/src/editor/swizzle/config.mjs diff --git a/packages/react-components/src/editor/swizzle/hooks/index.mjs b/packages/react/src/editor/swizzle/hooks/index.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/hooks/index.mjs rename to packages/react/src/editor/swizzle/hooks/index.mjs diff --git a/packages/react-components/src/editor/swizzle/hooks/use-account.mjs b/packages/react/src/editor/swizzle/hooks/use-account.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/hooks/use-account.mjs rename to packages/react/src/editor/swizzle/hooks/use-account.mjs diff --git a/packages/react-components/src/editor/swizzle/hooks/use-backend.mjs b/packages/react/src/editor/swizzle/hooks/use-backend.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/hooks/use-backend.mjs rename to packages/react/src/editor/swizzle/hooks/use-backend.mjs diff --git a/packages/react-components/src/editor/swizzle/hooks/use-editor-state.mjs b/packages/react/src/editor/swizzle/hooks/use-editor-state.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/hooks/use-editor-state.mjs rename to packages/react/src/editor/swizzle/hooks/use-editor-state.mjs diff --git a/packages/react-components/src/editor/swizzle/methods/core-settings.mjs b/packages/react/src/editor/swizzle/methods/core-settings.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/methods/core-settings.mjs rename to packages/react/src/editor/swizzle/methods/core-settings.mjs diff --git a/packages/react-components/src/editor/swizzle/methods/design-options.mjs b/packages/react/src/editor/swizzle/methods/design-options.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/methods/design-options.mjs rename to packages/react/src/editor/swizzle/methods/design-options.mjs diff --git a/packages/react-components/src/editor/swizzle/methods/editor.mjs b/packages/react/src/editor/swizzle/methods/editor.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/methods/editor.mjs rename to packages/react/src/editor/swizzle/methods/editor.mjs diff --git a/packages/react-components/src/editor/swizzle/methods/formatting.mjs b/packages/react/src/editor/swizzle/methods/formatting.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/methods/formatting.mjs rename to packages/react/src/editor/swizzle/methods/formatting.mjs diff --git a/packages/react-components/src/editor/swizzle/methods/index.mjs b/packages/react/src/editor/swizzle/methods/index.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/methods/index.mjs rename to packages/react/src/editor/swizzle/methods/index.mjs diff --git a/packages/react-components/src/editor/swizzle/methods/measurements.mjs b/packages/react/src/editor/swizzle/methods/measurements.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/methods/measurements.mjs rename to packages/react/src/editor/swizzle/methods/measurements.mjs diff --git a/packages/react-components/src/editor/swizzle/methods/ui-preferences.mjs b/packages/react/src/editor/swizzle/methods/ui-preferences.mjs similarity index 100% rename from packages/react-components/src/editor/swizzle/methods/ui-preferences.mjs rename to packages/react/src/editor/swizzle/methods/ui-preferences.mjs diff --git a/packages/react-components/src/editor/utils.mjs b/packages/react/src/editor/utils.mjs similarity index 100% rename from packages/react-components/src/editor/utils.mjs rename to packages/react/src/editor/utils.mjs diff --git a/packages/react-components/src/index.mjs b/packages/react/src/index.mjs similarity index 100% rename from packages/react-components/src/index.mjs rename to packages/react/src/index.mjs diff --git a/packages/react-components/src/linedrawings/aaron.mjs b/packages/react/src/linedrawings/aaron.mjs similarity index 100% rename from packages/react-components/src/linedrawings/aaron.mjs rename to packages/react/src/linedrawings/aaron.mjs diff --git a/packages/react-components/src/linedrawings/albert.mjs b/packages/react/src/linedrawings/albert.mjs similarity index 100% rename from packages/react-components/src/linedrawings/albert.mjs rename to packages/react/src/linedrawings/albert.mjs diff --git a/packages/react-components/src/linedrawings/bee.mjs b/packages/react/src/linedrawings/bee.mjs similarity index 100% rename from packages/react-components/src/linedrawings/bee.mjs rename to packages/react/src/linedrawings/bee.mjs diff --git a/packages/react-components/src/linedrawings/bella.mjs b/packages/react/src/linedrawings/bella.mjs similarity index 100% rename from packages/react-components/src/linedrawings/bella.mjs rename to packages/react/src/linedrawings/bella.mjs diff --git a/packages/react-components/src/linedrawings/benjamin.mjs b/packages/react/src/linedrawings/benjamin.mjs similarity index 100% rename from packages/react-components/src/linedrawings/benjamin.mjs rename to packages/react/src/linedrawings/benjamin.mjs diff --git a/packages/react-components/src/linedrawings/bent.mjs b/packages/react/src/linedrawings/bent.mjs similarity index 100% rename from packages/react-components/src/linedrawings/bent.mjs rename to packages/react/src/linedrawings/bent.mjs diff --git a/packages/react-components/src/linedrawings/bibi.mjs b/packages/react/src/linedrawings/bibi.mjs similarity index 100% rename from packages/react-components/src/linedrawings/bibi.mjs rename to packages/react/src/linedrawings/bibi.mjs diff --git a/packages/react-components/src/linedrawings/bob.mjs b/packages/react/src/linedrawings/bob.mjs similarity index 100% rename from packages/react-components/src/linedrawings/bob.mjs rename to packages/react/src/linedrawings/bob.mjs diff --git a/packages/react-components/src/linedrawings/breanna.mjs b/packages/react/src/linedrawings/breanna.mjs similarity index 100% rename from packages/react-components/src/linedrawings/breanna.mjs rename to packages/react/src/linedrawings/breanna.mjs diff --git a/packages/react-components/src/linedrawings/brian.mjs b/packages/react/src/linedrawings/brian.mjs similarity index 100% rename from packages/react-components/src/linedrawings/brian.mjs rename to packages/react/src/linedrawings/brian.mjs diff --git a/packages/react-components/src/linedrawings/bruce.mjs b/packages/react/src/linedrawings/bruce.mjs similarity index 100% rename from packages/react-components/src/linedrawings/bruce.mjs rename to packages/react/src/linedrawings/bruce.mjs diff --git a/packages/react-components/src/linedrawings/carlita.mjs b/packages/react/src/linedrawings/carlita.mjs similarity index 100% rename from packages/react-components/src/linedrawings/carlita.mjs rename to packages/react/src/linedrawings/carlita.mjs diff --git a/packages/react-components/src/linedrawings/carlton.mjs b/packages/react/src/linedrawings/carlton.mjs similarity index 100% rename from packages/react-components/src/linedrawings/carlton.mjs rename to packages/react/src/linedrawings/carlton.mjs diff --git a/packages/react-components/src/linedrawings/cathrin.mjs b/packages/react/src/linedrawings/cathrin.mjs similarity index 100% rename from packages/react-components/src/linedrawings/cathrin.mjs rename to packages/react/src/linedrawings/cathrin.mjs diff --git a/packages/react-components/src/linedrawings/charlie.mjs b/packages/react/src/linedrawings/charlie.mjs similarity index 100% rename from packages/react-components/src/linedrawings/charlie.mjs rename to packages/react/src/linedrawings/charlie.mjs diff --git a/packages/react-components/src/linedrawings/cornelius.mjs b/packages/react/src/linedrawings/cornelius.mjs similarity index 100% rename from packages/react-components/src/linedrawings/cornelius.mjs rename to packages/react/src/linedrawings/cornelius.mjs diff --git a/packages/react-components/src/linedrawings/diana.mjs b/packages/react/src/linedrawings/diana.mjs similarity index 100% rename from packages/react-components/src/linedrawings/diana.mjs rename to packages/react/src/linedrawings/diana.mjs diff --git a/packages/react-components/src/linedrawings/florence.mjs b/packages/react/src/linedrawings/florence.mjs similarity index 100% rename from packages/react-components/src/linedrawings/florence.mjs rename to packages/react/src/linedrawings/florence.mjs diff --git a/packages/react-components/src/linedrawings/florent.mjs b/packages/react/src/linedrawings/florent.mjs similarity index 100% rename from packages/react-components/src/linedrawings/florent.mjs rename to packages/react/src/linedrawings/florent.mjs diff --git a/packages/react-components/src/linedrawings/gozer.mjs b/packages/react/src/linedrawings/gozer.mjs similarity index 100% rename from packages/react-components/src/linedrawings/gozer.mjs rename to packages/react/src/linedrawings/gozer.mjs diff --git a/packages/react-components/src/linedrawings/hi.mjs b/packages/react/src/linedrawings/hi.mjs similarity index 100% rename from packages/react-components/src/linedrawings/hi.mjs rename to packages/react/src/linedrawings/hi.mjs diff --git a/packages/react-components/src/linedrawings/holmes.mjs b/packages/react/src/linedrawings/holmes.mjs similarity index 100% rename from packages/react-components/src/linedrawings/holmes.mjs rename to packages/react/src/linedrawings/holmes.mjs diff --git a/packages/react-components/src/linedrawings/hortensia.mjs b/packages/react/src/linedrawings/hortensia.mjs similarity index 100% rename from packages/react-components/src/linedrawings/hortensia.mjs rename to packages/react/src/linedrawings/hortensia.mjs diff --git a/packages/react-components/src/linedrawings/huey.mjs b/packages/react/src/linedrawings/huey.mjs similarity index 100% rename from packages/react-components/src/linedrawings/huey.mjs rename to packages/react/src/linedrawings/huey.mjs diff --git a/packages/react-components/src/linedrawings/hugo.mjs b/packages/react/src/linedrawings/hugo.mjs similarity index 100% rename from packages/react-components/src/linedrawings/hugo.mjs rename to packages/react/src/linedrawings/hugo.mjs diff --git a/packages/react-components/src/linedrawings/index.mjs b/packages/react/src/linedrawings/index.mjs similarity index 100% rename from packages/react-components/src/linedrawings/index.mjs rename to packages/react/src/linedrawings/index.mjs diff --git a/packages/react-components/src/linedrawings/lucy.mjs b/packages/react/src/linedrawings/lucy.mjs similarity index 100% rename from packages/react-components/src/linedrawings/lucy.mjs rename to packages/react/src/linedrawings/lucy.mjs diff --git a/packages/react-components/src/linedrawings/lumina.mjs b/packages/react/src/linedrawings/lumina.mjs similarity index 100% rename from packages/react-components/src/linedrawings/lumina.mjs rename to packages/react/src/linedrawings/lumina.mjs diff --git a/packages/react-components/src/linedrawings/lumira.mjs b/packages/react/src/linedrawings/lumira.mjs similarity index 100% rename from packages/react-components/src/linedrawings/lumira.mjs rename to packages/react/src/linedrawings/lumira.mjs diff --git a/packages/react-components/src/linedrawings/lunetius.mjs b/packages/react/src/linedrawings/lunetius.mjs similarity index 100% rename from packages/react-components/src/linedrawings/lunetius.mjs rename to packages/react/src/linedrawings/lunetius.mjs diff --git a/packages/react-components/src/linedrawings/noble.mjs b/packages/react/src/linedrawings/noble.mjs similarity index 100% rename from packages/react-components/src/linedrawings/noble.mjs rename to packages/react/src/linedrawings/noble.mjs diff --git a/packages/react-components/src/linedrawings/shared.mjs b/packages/react/src/linedrawings/shared.mjs similarity index 100% rename from packages/react-components/src/linedrawings/shared.mjs rename to packages/react/src/linedrawings/shared.mjs diff --git a/packages/react-components/src/linedrawings/simon.mjs b/packages/react/src/linedrawings/simon.mjs similarity index 100% rename from packages/react-components/src/linedrawings/simon.mjs rename to packages/react/src/linedrawings/simon.mjs diff --git a/packages/react-components/src/linedrawings/teagan.mjs b/packages/react/src/linedrawings/teagan.mjs similarity index 100% rename from packages/react-components/src/linedrawings/teagan.mjs rename to packages/react/src/linedrawings/teagan.mjs diff --git a/packages/react-components/src/linedrawings/tristan.mjs b/packages/react/src/linedrawings/tristan.mjs similarity index 100% rename from packages/react-components/src/linedrawings/tristan.mjs rename to packages/react/src/linedrawings/tristan.mjs diff --git a/packages/react-components/src/linedrawings/uma.mjs b/packages/react/src/linedrawings/uma.mjs similarity index 100% rename from packages/react-components/src/linedrawings/uma.mjs rename to packages/react/src/linedrawings/uma.mjs diff --git a/packages/react-components/src/linedrawings/umbra.mjs b/packages/react/src/linedrawings/umbra.mjs similarity index 100% rename from packages/react-components/src/linedrawings/umbra.mjs rename to packages/react/src/linedrawings/umbra.mjs diff --git a/packages/react-components/src/linedrawings/wahid.mjs b/packages/react/src/linedrawings/wahid.mjs similarity index 100% rename from packages/react-components/src/linedrawings/wahid.mjs rename to packages/react/src/linedrawings/wahid.mjs diff --git a/packages/react-components/src/pattern-xray/index.mjs b/packages/react/src/pattern-xray/index.mjs similarity index 100% rename from packages/react-components/src/pattern-xray/index.mjs rename to packages/react/src/pattern-xray/index.mjs diff --git a/packages/react-components/src/pattern-xray/path.mjs b/packages/react/src/pattern-xray/path.mjs similarity index 100% rename from packages/react-components/src/pattern-xray/path.mjs rename to packages/react/src/pattern-xray/path.mjs diff --git a/packages/react-components/src/pattern-xray/point.mjs b/packages/react/src/pattern-xray/point.mjs similarity index 100% rename from packages/react-components/src/pattern-xray/point.mjs rename to packages/react/src/pattern-xray/point.mjs diff --git a/packages/react-components/src/pattern/circle.mjs b/packages/react/src/pattern/circle.mjs similarity index 100% rename from packages/react-components/src/pattern/circle.mjs rename to packages/react/src/pattern/circle.mjs diff --git a/packages/react-components/src/pattern/defs.mjs b/packages/react/src/pattern/defs.mjs similarity index 100% rename from packages/react-components/src/pattern/defs.mjs rename to packages/react/src/pattern/defs.mjs diff --git a/packages/react-components/src/pattern/grid.mjs b/packages/react/src/pattern/grid.mjs similarity index 100% rename from packages/react-components/src/pattern/grid.mjs rename to packages/react/src/pattern/grid.mjs diff --git a/packages/react-components/src/pattern/group.mjs b/packages/react/src/pattern/group.mjs similarity index 100% rename from packages/react-components/src/pattern/group.mjs rename to packages/react/src/pattern/group.mjs diff --git a/packages/react-components/src/pattern/index.mjs b/packages/react/src/pattern/index.mjs similarity index 100% rename from packages/react-components/src/pattern/index.mjs rename to packages/react/src/pattern/index.mjs diff --git a/packages/react-components/src/pattern/part.mjs b/packages/react/src/pattern/part.mjs similarity index 100% rename from packages/react-components/src/pattern/part.mjs rename to packages/react/src/pattern/part.mjs diff --git a/packages/react-components/src/pattern/path.mjs b/packages/react/src/pattern/path.mjs similarity index 100% rename from packages/react-components/src/pattern/path.mjs rename to packages/react/src/pattern/path.mjs diff --git a/packages/react-components/src/pattern/point.mjs b/packages/react/src/pattern/point.mjs similarity index 100% rename from packages/react-components/src/pattern/point.mjs rename to packages/react/src/pattern/point.mjs diff --git a/packages/react-components/src/pattern/snippet.mjs b/packages/react/src/pattern/snippet.mjs similarity index 100% rename from packages/react-components/src/pattern/snippet.mjs rename to packages/react/src/pattern/snippet.mjs diff --git a/packages/react-components/src/pattern/stack.mjs b/packages/react/src/pattern/stack.mjs similarity index 100% rename from packages/react-components/src/pattern/stack.mjs rename to packages/react/src/pattern/stack.mjs diff --git a/packages/react-components/src/pattern/svg.mjs b/packages/react/src/pattern/svg.mjs similarity index 100% rename from packages/react-components/src/pattern/svg.mjs rename to packages/react/src/pattern/svg.mjs diff --git a/packages/react-components/src/pattern/text.mjs b/packages/react/src/pattern/text.mjs similarity index 100% rename from packages/react-components/src/pattern/text.mjs rename to packages/react/src/pattern/text.mjs diff --git a/packages/react-components/src/pattern/utils.mjs b/packages/react/src/pattern/utils.mjs similarity index 100% rename from packages/react-components/src/pattern/utils.mjs rename to packages/react/src/pattern/utils.mjs diff --git a/packages/react-components/src/popout.mjs b/packages/react/src/popout.mjs similarity index 100% rename from packages/react-components/src/popout.mjs rename to packages/react/src/popout.mjs diff --git a/packages/react-components/src/utils.mjs b/packages/react/src/utils.mjs similarity index 66% rename from packages/react-components/src/utils.mjs rename to packages/react/src/utils.mjs index 0f06f2953ce..83045fd3f5c 100644 --- a/packages/react-components/src/utils.mjs +++ b/packages/react/src/utils.mjs @@ -4,8 +4,8 @@ * @param {mixed} obj - The value to check * @return {bool} result - True of obj is of type object */ -export function isObject (obj) { - return (typeof obj === 'object' && !Array.isArray(obj)) +export function isObject(obj) { + return typeof obj === 'object' && !Array.isArray(obj) } /* @@ -16,13 +16,12 @@ export function isObject (obj) { * @param {object} methods - Any swizzled methods to add * @return {object} props - The merged props object */ -export function mergeProps (props, components=false, methods=false) { - const Swizzled = isObject(props.Swizzled) - ? props.Swizzled - : { components: {}, methods: {} } +export function mergeProps(props, components = false, methods = false) { + const Swizzled = isObject(props.Swizzled) ? props.Swizzled : { components: {}, methods: {} } if (components) { - if (isObject(Swizzled.components)) Swizzled.components = { ...components, ...Swizzled.components } + if (isObject(Swizzled.components)) + Swizzled.components = { ...components, ...Swizzled.components } else Swizzled.components = components } @@ -33,5 +32,3 @@ export function mergeProps (props, components=false, methods=false) { return { ...props, Swizzled } } - -