├── .eslintrc ├── .gitignore ├── .nvmrc ├── .prettierrc ├── .storybook ├── addons.js ├── config.js └── webpack.config.js ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── config ├── env.js ├── jest │ ├── cssTransform.js │ └── fileTransform.js ├── paths.js ├── polyfills.js ├── webpack.config.demo.js ├── webpack.config.dev.js ├── webpack.config.prod.js └── webpackDevServer.config.js ├── jest-test-results.json ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html └── manifest.json ├── scripts ├── build.js ├── demo.js ├── start.js └── test.js ├── src ├── assets │ ├── inrupt_logo.png │ ├── shexj.json │ └── solid_logo.png ├── demo │ ├── App.js │ ├── components │ │ ├── HandleShexForm │ │ │ ├── handle-shex-form.component.js │ │ │ └── index.js │ │ └── index.js │ ├── index.js │ └── registerServiceWorker.js ├── lib │ ├── classes │ │ ├── access-control-factory.js │ │ ├── access-control-list.js │ │ ├── access-control-list.test.js │ │ ├── app-permissions.js │ │ ├── index.js │ │ ├── notification.js │ │ └── notifications.test.js │ ├── components │ │ ├── FormModel │ │ │ ├── children │ │ │ │ ├── Form │ │ │ │ │ └── UI │ │ │ │ │ │ ├── CheckBox │ │ │ │ │ │ ├── check-box.component.js │ │ │ │ │ │ ├── check-box.styles.js │ │ │ │ │ │ ├── check-box.test.js │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── CheckBoxList │ │ │ │ │ │ ├── check-box-list.component.js │ │ │ │ │ │ ├── check-box-list.test.js │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── Classifier │ │ │ │ │ │ ├── classifier.component.js │ │ │ │ │ │ ├── classifier.style.js │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── ColorPicker │ │ │ │ │ │ ├── color-picker.component.js │ │ │ │ │ │ ├── color-picker.styles.js │ │ │ │ │ │ ├── color-picker.test.js │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── Comment │ │ │ │ │ │ ├── comment.component.js │ │ │ │ │ │ ├── comment.test.js │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── DateTimePicker │ │ │ │ │ │ ├── date-time-picker.component.js │ │ │ │ │ │ ├── date-time-picker.test.js │ │ │ │ │ │ ├── date-time.styles.js │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── Decimal │ │ │ │ │ │ ├── decimal.component.js │ │ │ │ │ │ ├── decimal.test.js │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── DeleteButton │ │ │ │ │ │ ├── delete-button.component.js │ │ │ │ │ │ ├── delete-button.test.js │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── Email │ │ │ │ │ │ ├── email.component.js │ │ │ │ │ │ ├── email.test.js │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── ErrorMessage │ │ │ │ │ │ ├── error-message.component.js │ │ │ │ │ │ ├── error-message.styled.js │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── Float │ │ │ │ │ │ ├── float.component.js │ │ │ │ │ │ ├── float.test.js │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── Heading │ │ │ │ │ │ ├── heading.component.js │ │ │ │ │ │ ├── heading.test.js │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── Input │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── input.component.js │ │ │ │ │ │ ├── input.styles.js │ │ │ │ │ │ └── input.test.js │ │ │ │ │ │ ├── Integer │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── integer.component.js │ │ │ │ │ │ └── integer.test.js │ │ │ │ │ │ ├── Phone │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── phone.component.js │ │ │ │ │ │ └── phone.test.js │ │ │ │ │ │ ├── RadioButton │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── radio-button.component.js │ │ │ │ │ │ └── radio-button.test.js │ │ │ │ │ │ ├── RadioButtonList │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── radio-button-list.component.js │ │ │ │ │ │ └── radio-button-list.test.js │ │ │ │ │ │ ├── Select │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── select.component.js │ │ │ │ │ │ └── select.test.js │ │ │ │ │ │ ├── TextArea │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── text-area.component.js │ │ │ │ │ │ ├── text-area.styles.js │ │ │ │ │ │ └── text-area.test.js │ │ │ │ │ │ ├── component-mapping.js │ │ │ │ │ │ └── index.js │ │ │ │ ├── Group │ │ │ │ │ ├── group.component.js │ │ │ │ │ ├── group.style.js │ │ │ │ │ └── index.js │ │ │ │ ├── Multiple │ │ │ │ │ ├── index.js │ │ │ │ │ └── multiple.component.js │ │ │ │ ├── Spinner │ │ │ │ │ ├── index.js │ │ │ │ │ └── spinner.component.js │ │ │ │ └── Viewer │ │ │ │ │ ├── UI │ │ │ │ │ ├── BoolLine │ │ │ │ │ │ ├── bool-line.component.js │ │ │ │ │ │ ├── bool-line.style.js │ │ │ │ │ │ ├── bool-line.test.js │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── ColorLine │ │ │ │ │ │ ├── color-line.component.js │ │ │ │ │ │ ├── color-line.style.js │ │ │ │ │ │ ├── color-line.test.js │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── DateLine │ │ │ │ │ │ ├── date-line.component.js │ │ │ │ │ │ ├── date-line.style.js │ │ │ │ │ │ ├── date-line.test.js │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── MultiLine │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── multi-line.component.js │ │ │ │ │ │ ├── multi-line.style.js │ │ │ │ │ │ └── multi-line.test.js │ │ │ │ │ ├── MultipleViewer │ │ │ │ │ │ └── multiple-viewer.component.js │ │ │ │ │ ├── SingleLine │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── single-line.component.js │ │ │ │ │ │ ├── single-line.style.js │ │ │ │ │ │ └── single-line.test.js │ │ │ │ │ └── ui-mapping.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── viewer.component.js │ │ │ │ │ └── viewer.style.js │ │ │ ├── form-model-example.json │ │ │ ├── form-model.component.js │ │ │ ├── index.js │ │ │ └── live-form-model.component.js │ │ ├── PrivateRoute │ │ │ ├── index.js │ │ │ ├── private-route.component.js │ │ │ ├── private-route.component.test.js │ │ │ └── private-route.style.js │ │ ├── ProfileUploader │ │ │ ├── index.js │ │ │ ├── profile-uploader.component.js │ │ │ ├── profile-uploader.style.js │ │ │ └── profile-uploader.test.js │ │ ├── ProfileViewer │ │ │ ├── index.js │ │ │ ├── profile-viewer.component.js │ │ │ └── profile-viewer.style.js │ │ ├── ProviderLogin │ │ │ ├── children │ │ │ │ └── Form │ │ │ │ │ ├── form.presentational.js │ │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ ├── provider-login.container.js │ │ │ └── provider-login.container.test.js │ │ ├── ProviderSelect │ │ │ ├── index.js │ │ │ ├── provider.select.component.js │ │ │ ├── provider.select.component.test.js │ │ │ └── styled.components.js │ │ ├── ShexForm │ │ │ ├── children │ │ │ │ ├── AddButton │ │ │ │ │ ├── add-button.component.js │ │ │ │ │ ├── add-button.component.test.js │ │ │ │ │ └── index.js │ │ │ │ ├── DeleteButton │ │ │ │ │ ├── delete-button.component.js │ │ │ │ │ ├── delete-button.component.test.js │ │ │ │ │ └── index.js │ │ │ │ ├── DropDownField │ │ │ │ │ ├── dropdown-field.component.js │ │ │ │ │ ├── dropdown-field.component.test.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── styled.component.js │ │ │ │ ├── Field │ │ │ │ │ ├── field.component.js │ │ │ │ │ ├── field.component.test.js │ │ │ │ │ └── index.js │ │ │ │ ├── InputField │ │ │ │ │ ├── index.js │ │ │ │ │ ├── input-field.component.js │ │ │ │ │ ├── input-field.component.test.js │ │ │ │ │ └── styled.component.js │ │ │ │ ├── expression-fields.component.js │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ ├── shex-form.component.js │ │ │ ├── shexj.json │ │ │ └── styled.component.js │ │ ├── ShexFormBuilder │ │ │ ├── children │ │ │ │ └── ShexFormLive │ │ │ │ │ ├── index.js │ │ │ │ │ ├── shex-form-live.component.js │ │ │ │ │ └── styled.component.js │ │ │ ├── index.js │ │ │ ├── shex-form-builder.component.js │ │ │ └── shex-form-builder.component.test.js │ │ ├── Uploader │ │ │ ├── index.js │ │ │ ├── uploader.component.js │ │ │ └── uploader.test.js │ │ ├── index.js │ │ └── withAuthorization │ │ │ ├── index.js │ │ │ ├── with-authorization.component.js │ │ │ └── with-authorization.test.js │ ├── constants │ │ └── index.js │ ├── context │ │ ├── ThemeContext.js │ │ ├── formModel.provider.js │ │ ├── index.js │ │ └── shex.provider.js │ ├── entities │ │ └── index.js │ ├── hooks │ │ ├── index.js │ │ ├── useNotification.js │ │ ├── useNotification.test.js │ │ ├── useShex.js │ │ └── useShex.test.js │ ├── index.js │ ├── shapes │ │ └── notification.json │ ├── styled-components │ │ ├── form.js │ │ └── index.js │ └── utils │ │ ├── datestimes.test.js │ │ ├── datetimes.js │ │ ├── error.js │ │ ├── index.js │ │ ├── shex.js │ │ ├── shexFormValidator.js │ │ ├── solidFetch.js │ │ └── statusMessage.js └── test │ └── __mocks__ │ ├── @solid │ └── query-ldflex.js │ └── solid-auth-client.js └── stories ├── Image ├── README.md └── image.stories.js ├── LogoutButton ├── README.md └── logout-button.stories.js ├── PrivateRoute ├── README.md └── private-route.stories.js ├── ProfileUploader ├── README.md └── profile-uploader.stories.js ├── ProviderLogin ├── README.md └── provider-login.stories.js ├── ShexForm ├── README.md └── shex-form.stories.js ├── Uploader ├── README.md └── uploader.stories.js ├── withAuthorization ├── README.md └── with-authorization.stories.js └── withWebId ├── README.md └── with-webid.stories.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": ["react-app", "airbnb", "prettier"], 4 | "plugins": ["react", "prettier"], 5 | "rules": { 6 | "prettier/prettier": [1], 7 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }], 8 | "no-underscore-dangle": [0], 9 | "import/no-unresolved": [0], 10 | "no-unused-vars": [1], 11 | "react/prop-types": [1], 12 | "no-shadow": [0], 13 | "no-restricted-syntax": [0], 14 | "consistent-return": [0], 15 | "import/prefer-default-export": [0], 16 | "import/no-cycle": [0], 17 | "quotes": [1, "single"], 18 | "react/no-array-index-key": [1], 19 | "react/jsx-one-expression-per-line": [0], 20 | "jsx-a11y/label-has-for": [0] 21 | }, 22 | "settings": { 23 | "import/resolver": { "babel-module": {} } 24 | }, 25 | "parserOptions": { 26 | "ecmaFeatures": { 27 | "jsx": true, 28 | "modules": true 29 | } 30 | }, 31 | "env": { 32 | "browser": true, 33 | "jest": true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # production 7 | /build 8 | /demo 9 | 10 | # testing 11 | /coverage 12 | 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | # editors 22 | .idea 23 | *.iml 24 | 25 | npm-debug.log* 26 | yarn-debug.log* 27 | yarn-error.log* 28 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v12.7.0 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "printWidth": 100 4 | } 5 | -------------------------------------------------------------------------------- /.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import '@storybook/addons'; 2 | import '@storybook/addon-console'; 3 | import 'storybook-readme/register'; 4 | import '@storybook/addon-knobs/register'; 5 | import '@storybook/addon-actions/register'; 6 | import '@storybook/addon-jest/register'; 7 | import 'storybook-addon-jsx/register'; 8 | -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { configure, addDecorator } from '@storybook/react'; 2 | import { addReadme } from 'storybook-readme'; 3 | import { withTests } from '@storybook/addon-jest'; 4 | import StoryRouter from 'storybook-react-router'; 5 | 6 | import results from '../jest-test-results.json'; 7 | 8 | import { jsxDecorator } from 'storybook-addon-jsx'; 9 | 10 | addDecorator(jsxDecorator); 11 | 12 | addDecorator( 13 | withTests({ 14 | results 15 | }) 16 | ); 17 | addDecorator(addReadme); 18 | 19 | addDecorator(StoryRouter()); 20 | 21 | // automatically import all files ending in *.stories.js 22 | const req = require.context('../stories', true, /.stories.js$/); 23 | function loadStories() { 24 | req.keys().forEach(filename => req(filename)); 25 | } 26 | 27 | configure(loadStories, module); 28 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 'node' 4 | script: 5 | - npm run test 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the Solid React Components Library 2 | 3 | Thank you for your interest in contributing to the Solid React Components Library! 4 | 5 | Before getting started, please review the [Solid React SDK Contributor Guide](https://github.com/Inrupt-inc/solid-react-sdk/blob/master/CONTRIBUTING.md). 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Inrupt 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 | -------------------------------------------------------------------------------- /config/env.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const paths = require('./paths'); 4 | 5 | // Make sure that including paths.js after env.js will read .env variables. 6 | delete require.cache[require.resolve('./paths')]; 7 | 8 | const NODE_ENV = process.env.NODE_ENV; 9 | if (!NODE_ENV) { 10 | throw new Error('The NODE_ENV environment variable is required but was not specified.'); 11 | } 12 | 13 | // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use 14 | var dotenvFiles = [ 15 | `${paths.dotenv}.${NODE_ENV}.local`, 16 | `${paths.dotenv}.${NODE_ENV}`, 17 | // Don't include `.env.local` for `test` environment 18 | // since normally you expect tests to produce the same 19 | // results for everyone 20 | NODE_ENV !== 'test' && `${paths.dotenv}.local`, 21 | paths.dotenv 22 | ].filter(Boolean); 23 | 24 | // Load environment variables from .env* files. Suppress warnings using silent 25 | // if this file is missing. dotenv will never modify any environment variables 26 | // that have already been set. 27 | // https://github.com/motdotla/dotenv 28 | dotenvFiles.forEach(dotenvFile => { 29 | if (fs.existsSync(dotenvFile)) { 30 | require('dotenv').config({ 31 | path: dotenvFile 32 | }); 33 | } 34 | }); 35 | 36 | // We support resolving modules according to `NODE_PATH`. 37 | // This lets you use absolute paths in imports inside large monorepos: 38 | // https://github.com/facebookincubator/create-react-app/issues/253. 39 | // It works similar to `NODE_PATH` in Node itself: 40 | // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders 41 | // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. 42 | // Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. 43 | // https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421 44 | // We also resolve them to make sure all tools using them work consistently. 45 | const appDirectory = fs.realpathSync(process.cwd()); 46 | process.env.NODE_PATH = (process.env.NODE_PATH || '') 47 | .split(path.delimiter) 48 | .filter(folder => folder && !path.isAbsolute(folder)) 49 | .map(folder => path.resolve(appDirectory, folder)) 50 | .join(path.delimiter); 51 | 52 | // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be 53 | // injected into the application via DefinePlugin in Webpack configuration. 54 | const REACT_APP = /^REACT_APP_/i; 55 | 56 | function getClientEnvironment(publicUrl) { 57 | const raw = Object.keys(process.env) 58 | .filter(key => REACT_APP.test(key)) 59 | .reduce( 60 | (env, key) => { 61 | env[key] = process.env[key]; 62 | return env; 63 | }, 64 | { 65 | // Useful for determining whether we’re running in production mode. 66 | // Most importantly, it switches React into the correct mode. 67 | NODE_ENV: process.env.NODE_ENV || 'development', 68 | // Useful for resolving the correct path to static assets in `public`. 69 | // For example, . 70 | // This should only be used as an escape hatch. Normally you would put 71 | // images into the `src` and `import` them in code to get their paths. 72 | PUBLIC_URL: publicUrl 73 | } 74 | ); 75 | // Stringify all values so we can feed into Webpack DefinePlugin 76 | const stringified = { 77 | 'process.env': Object.keys(raw).reduce((env, key) => { 78 | env[key] = JSON.stringify(raw[key]); 79 | return env; 80 | }, {}) 81 | }; 82 | 83 | return { raw, stringified }; 84 | } 85 | 86 | module.exports = getClientEnvironment; 87 | -------------------------------------------------------------------------------- /config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | // This is a custom Jest transformer turning style imports into empty objects. 2 | // http://facebook.github.io/jest/docs/tutorial-webpack.html 3 | 4 | module.exports = { 5 | process() { 6 | return 'module.exports = {};'; 7 | }, 8 | getCacheKey() { 9 | // The output is always the same. 10 | return 'cssTransform'; 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | // This is a custom Jest transformer turning file imports into filenames. 4 | // http://facebook.github.io/jest/docs/tutorial-webpack.html 5 | 6 | module.exports = { 7 | process(src, filename) { 8 | return `module.exports = ${JSON.stringify(path.basename(filename))};`; 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /config/paths.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-dynamic-require */ 2 | /* eslint-disable global-require */ 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const url = require('url'); 6 | 7 | // Make sure any symlinks in the project folder are resolved: 8 | // https://github.com/facebook/create-react-app/issues/637 9 | const appDirectory = fs.realpathSync(process.cwd()); 10 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath); 11 | 12 | const envPublicUrl = process.env.PUBLIC_URL; 13 | 14 | function ensureSlash(inputPath, needsSlash) { 15 | const hasSlash = inputPath.endsWith('/'); 16 | if (hasSlash && !needsSlash) { 17 | return inputPath.substr(0, inputPath.length - 1); 18 | } 19 | if (!hasSlash && needsSlash) { 20 | return `${inputPath}/`; 21 | } 22 | return inputPath; 23 | } 24 | 25 | const getPublicUrl = appPackageJson => envPublicUrl || require(appPackageJson).homepage; 26 | 27 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer 28 | // "public path" at which the app is served. 29 | // Webpack needs to know it to put the right