@linktr.ee/create-link-app 0.3.0-next.3 → 0.3.0-next.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -0
- package/dist/commands/build.js +3 -2
- package/dist/commands/dev.js +2 -1
- package/dist/commands/generate-types.js +111 -0
- package/dist/commands/storybook.js +28 -0
- package/dist/lib/create/create-project.js +3 -0
- package/dist/lib/deploy/pack-project.js +12 -1
- package/dist/lib/schema/compile.js +31 -0
- package/dist/postcss/postcss.config.js +21 -0
- package/dist/storybook/global.css +53 -0
- package/dist/storybook/main.js +62 -0
- package/dist/storybook/preview.js +13 -0
- package/dist/webpack/webpack.config.js +55 -4
- package/html-template/development.html +1 -1
- package/html-template/production.html +1 -1
- package/oclif.manifest.json +32 -1
- package/package.json +28 -3
- package/templates/common/README.md +38 -17
- package/templates/common/fixtures/props-data.json +1 -2
- package/templates/common/gitignore +1 -0
- package/templates/common/schema/editablePrivate.jtd.json +6 -0
- package/templates/common/schema/editablePublic.jtd.json +10 -0
- package/templates/common/schema/readonlyPrivate.jtd.json +8 -0
- package/templates/common/schema/readonlyPublic.jtd.json +6 -0
- package/templates/common/schema/system.jtd.json +6 -0
- package/templates/common/settings.json +11 -23
- package/templates/react/package.json +5 -2
- package/templates/react/src/index.jsx +4 -13
- package/templates/react/src/tailwind.css +5 -0
- package/templates/react-ts/package.json +5 -2
- package/templates/react-ts/src/components/Layouts.tsx +57 -0
- package/templates/react-ts/src/index.tsx +20 -14
- package/templates/react-ts/src/stories/LinkApp.stories.tsx +99 -0
- package/templates/react-ts/src/stories/tailwind.sb.css +5 -0
- package/templates/react-ts/src/tailwind.css +4 -0
- package/templates/react-ts/src/types/global.d.ts +8 -5
- package/templates/react-ts/src/types/index.ts +8 -7
- package/templates/react-ts/src/types/schema/index.ts +33 -0
- package/templates/react/src/images/logo.png +0 -0
- package/templates/react-ts/src/images/logo.png +0 -0
package/README.md
CHANGED
|
@@ -23,10 +23,12 @@ yarn create @linktr.ee/create-link-app my-link-app
|
|
|
23
23
|
* [`create-link-app create NAME`](#create-link-app-create-name)
|
|
24
24
|
* [`create-link-app deploy`](#create-link-app-deploy)
|
|
25
25
|
* [`create-link-app dev`](#create-link-app-dev)
|
|
26
|
+
* [`create-link-app generate-types`](#create-link-app-generate-types)
|
|
26
27
|
* [`create-link-app grant-access LINK_APP_ID USERNAME`](#create-link-app-grant-access-link_app_id-username)
|
|
27
28
|
* [`create-link-app help [COMMANDS]`](#create-link-app-help-commands)
|
|
28
29
|
* [`create-link-app login`](#create-link-app-login)
|
|
29
30
|
* [`create-link-app logout`](#create-link-app-logout)
|
|
31
|
+
* [`create-link-app storybook`](#create-link-app-storybook)
|
|
30
32
|
|
|
31
33
|
## `create-link-app build`
|
|
32
34
|
|
|
@@ -106,6 +108,18 @@ EXAMPLES
|
|
|
106
108
|
$ create-link-app dev --https
|
|
107
109
|
```
|
|
108
110
|
|
|
111
|
+
## `create-link-app generate-types`
|
|
112
|
+
|
|
113
|
+
Generate Typescript types from the schema definitions
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
USAGE
|
|
117
|
+
$ create-link-app generate-types
|
|
118
|
+
|
|
119
|
+
DESCRIPTION
|
|
120
|
+
Generate Typescript types from the schema definitions
|
|
121
|
+
```
|
|
122
|
+
|
|
109
123
|
## `create-link-app grant-access LINK_APP_ID USERNAME`
|
|
110
124
|
|
|
111
125
|
Grant access to other developers to push updates for your Link App
|
|
@@ -168,4 +182,19 @@ USAGE
|
|
|
168
182
|
DESCRIPTION
|
|
169
183
|
Logout and clear browser session
|
|
170
184
|
```
|
|
185
|
+
|
|
186
|
+
## `create-link-app storybook`
|
|
187
|
+
|
|
188
|
+
Start the Storybook development server
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
USAGE
|
|
192
|
+
$ create-link-app storybook [-p <value>]
|
|
193
|
+
|
|
194
|
+
FLAGS
|
|
195
|
+
-p, --port=<value> [default: 6006] Port to run the Storybook server on
|
|
196
|
+
|
|
197
|
+
DESCRIPTION
|
|
198
|
+
Start the Storybook development server
|
|
199
|
+
```
|
|
171
200
|
<!-- commandsstop -->
|
package/dist/commands/build.js
CHANGED
|
@@ -10,9 +10,10 @@ const webpack_config_1 = __importDefault(require("../webpack/webpack.config"));
|
|
|
10
10
|
class Build extends base_1.default {
|
|
11
11
|
async run() {
|
|
12
12
|
const { flags } = await this.parse(Build);
|
|
13
|
-
|
|
13
|
+
const config = await (0, webpack_config_1.default)('production', {
|
|
14
14
|
allowAnyOrigin: flags['allow-any-origin'],
|
|
15
|
-
})
|
|
15
|
+
});
|
|
16
|
+
(0, webpack_1.default)(config, (err, stats) => {
|
|
16
17
|
if (err) {
|
|
17
18
|
this.error(err);
|
|
18
19
|
}
|
package/dist/commands/dev.js
CHANGED
|
@@ -11,6 +11,7 @@ const webpack_config_1 = __importDefault(require("../webpack/webpack.config"));
|
|
|
11
11
|
class Dev extends base_1.default {
|
|
12
12
|
async run() {
|
|
13
13
|
const { flags } = await this.parse(Dev);
|
|
14
|
+
const config = await (0, webpack_config_1.default)('development');
|
|
14
15
|
const devServer = new webpack_dev_server_1.default({
|
|
15
16
|
client: {
|
|
16
17
|
overlay: false,
|
|
@@ -18,7 +19,7 @@ class Dev extends base_1.default {
|
|
|
18
19
|
hot: false,
|
|
19
20
|
https: flags.https,
|
|
20
21
|
port: flags.port,
|
|
21
|
-
}, (0, webpack_1.default)(
|
|
22
|
+
}, (0, webpack_1.default)(config));
|
|
22
23
|
await devServer.start();
|
|
23
24
|
}
|
|
24
25
|
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const path_1 = __importDefault(require("path"));
|
|
7
|
+
const base_1 = __importDefault(require("../base"));
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
class MissingDependencyException extends Error {
|
|
10
|
+
constructor(packageName) {
|
|
11
|
+
super(`'${packageName}' is required on your system. Please refer to the create-link-app README`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const ucfirst = (str) => {
|
|
15
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
16
|
+
};
|
|
17
|
+
class GenerateTypes extends base_1.default {
|
|
18
|
+
constructor() {
|
|
19
|
+
super(...arguments);
|
|
20
|
+
this.schemaDirPath = path_1.default.join(process.cwd(), '/schema');
|
|
21
|
+
this.tmpPath = path_1.default.join(process.cwd(), '/__temp__');
|
|
22
|
+
this.typesPath = path_1.default.join(process.cwd(), '/src/types/schema');
|
|
23
|
+
}
|
|
24
|
+
async run() {
|
|
25
|
+
try {
|
|
26
|
+
// Check for necessary deps
|
|
27
|
+
await this.dependOn('prettier');
|
|
28
|
+
await this.dependOn('jtd-codegen');
|
|
29
|
+
await this.log('✓ All dependencies present');
|
|
30
|
+
// Ensure necessary directories exist
|
|
31
|
+
await this.cmd(`mkdir -p ${this.tmpPath} && touch ${this.tmpPath}/index.ts`);
|
|
32
|
+
await this.cmd(`mkdir -p ${this.typesPath} && touch ${this.typesPath}/index.ts`);
|
|
33
|
+
await this.log('✓ Files prepped for generation');
|
|
34
|
+
// Wipe existing types & drop comments
|
|
35
|
+
await this.cmd(`> ${this.typesPath}/index.ts`);
|
|
36
|
+
await this.cmd(`echo "/**" >> ${this.typesPath}/index.ts`);
|
|
37
|
+
await this.cmd(`echo " * These types were autogenerated by @linktr.ee/create-link-app" >> ${this.typesPath}/index.ts`);
|
|
38
|
+
await this.cmd(`echo " * https://www.npmjs.com/package/@linktr.ee/create-link-app " >> ${this.typesPath}/index.ts`);
|
|
39
|
+
await this.cmd(`echo " */" >> ${this.typesPath}/index.ts`);
|
|
40
|
+
// Generate and append types
|
|
41
|
+
await this.generateAndAppendSchemaType('editablePublic');
|
|
42
|
+
await this.log('✓ Generated EditablePublicData type');
|
|
43
|
+
await this.generateAndAppendSchemaType('readonlyPublic');
|
|
44
|
+
await this.log('✓ Generated ReadonlyPublicData type');
|
|
45
|
+
await this.generateAndAppendSchemaType('editablePrivate');
|
|
46
|
+
await this.log('✓ Generated EditablePrivateData type');
|
|
47
|
+
await this.generateAndAppendSchemaType('readonlyPrivate');
|
|
48
|
+
await this.log('✓ Generated ReadonlyPrivateData type');
|
|
49
|
+
// Clean up file formatting
|
|
50
|
+
await this.cmd(`prettier ${this.typesPath}/index.ts --write`);
|
|
51
|
+
await this.log('✓ All types created successfully');
|
|
52
|
+
// Garbage collect temporary dir
|
|
53
|
+
await this.cmd(`rm -rf ${this.tmpPath}`);
|
|
54
|
+
await this.log('✓ Cleanup complete');
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
await this.log(`𐄂 ERROR: ${e}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Generates a Typescript type for the schema defined in schema/<schemaName>.jtd.json
|
|
62
|
+
* and appends that type to src/types/schema/index.ts
|
|
63
|
+
*/
|
|
64
|
+
async generateAndAppendSchemaType(schemaName) {
|
|
65
|
+
// Generate schema
|
|
66
|
+
await this.cmd(`jtd-codegen ${this.schemaDirPath}/${schemaName}.jtd.json --typescript-out ${this.tmpPath} --root-name=${ucfirst(schemaName)}Data`);
|
|
67
|
+
// Strip jtd comment
|
|
68
|
+
await this.cmd(`sed '/^\\/\\//d' ${this.tmpPath}/index.ts > ${this.tmpPath}/parsed.ts`);
|
|
69
|
+
// Append to final file
|
|
70
|
+
await this.cmd(`cat ${this.tmpPath}/parsed.ts >> ${this.typesPath}/index.ts`);
|
|
71
|
+
}
|
|
72
|
+
async dependOn(dependencyName) {
|
|
73
|
+
try {
|
|
74
|
+
await this.cmd(`command -v ${dependencyName} || exit 1`);
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
throw new MissingDependencyException('prettier');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Run a command with spawn effectively synchronously
|
|
82
|
+
*/
|
|
83
|
+
async cmd(command, opts = {
|
|
84
|
+
shell: true,
|
|
85
|
+
stdio: 'ignore',
|
|
86
|
+
}, onError) {
|
|
87
|
+
await new Promise((resolve, reject) => {
|
|
88
|
+
(0, child_process_1.spawn)(command, opts)
|
|
89
|
+
.on('error', (e) => {
|
|
90
|
+
reject(e);
|
|
91
|
+
})
|
|
92
|
+
.on('exit', (code) => {
|
|
93
|
+
if (code === 1)
|
|
94
|
+
reject({ exitCode: code });
|
|
95
|
+
})
|
|
96
|
+
.on('close', () => {
|
|
97
|
+
resolve();
|
|
98
|
+
});
|
|
99
|
+
}).catch((e) => {
|
|
100
|
+
if (onError) {
|
|
101
|
+
onError();
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
throw e;
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
exports.default = GenerateTypes;
|
|
111
|
+
GenerateTypes.description = 'Generate Typescript types from the schema definitions';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const core_1 = require("@oclif/core");
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const base_1 = __importDefault(require("../base"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
class Storybook extends base_1.default {
|
|
11
|
+
async run() {
|
|
12
|
+
const configPath = path_1.default.resolve(__dirname, '..', 'storybook');
|
|
13
|
+
const { flags } = await this.parse(Storybook);
|
|
14
|
+
const storybook = (0, child_process_1.spawn)(`start-storybook -p ${flags.port} -c ${configPath}`, { shell: true, stdio: 'inherit' });
|
|
15
|
+
storybook.on('error', (err) => {
|
|
16
|
+
throw err;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.default = Storybook;
|
|
21
|
+
Storybook.description = 'Start the Storybook development server';
|
|
22
|
+
Storybook.flags = {
|
|
23
|
+
port: core_1.Flags.integer({
|
|
24
|
+
char: 'p',
|
|
25
|
+
description: 'Port to run the Storybook server on',
|
|
26
|
+
default: 6006,
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
@@ -14,6 +14,9 @@ const createProject = async (template, targetDir) => {
|
|
|
14
14
|
await fs_extra_1.default.copy(templateDir, targetDir);
|
|
15
15
|
await fs_extra_1.default.copy(templateCommonDir, targetDir);
|
|
16
16
|
await fs_extra_1.default.move(`${targetDir}/gitignore`, `${targetDir}/.gitignore`);
|
|
17
|
+
if (await fs_extra_1.default.existsSync(`${targetDir}/src/types/global.d.ts`)) {
|
|
18
|
+
await fs_extra_1.default.unlink(`${targetDir}/src/types/global.d.ts`);
|
|
19
|
+
}
|
|
17
20
|
// update `name` field in project manifest
|
|
18
21
|
const manifest = await fs_extra_1.default.readJson(`${targetDir}/manifest.json`);
|
|
19
22
|
manifest.name = (0, project_name_to_title_1.default)(path_1.default.basename(targetDir));
|
|
@@ -8,7 +8,13 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
/**
|
|
10
10
|
* Pack the Link App source files into `package.tgz`. This includes the following:
|
|
11
|
+
* - `schema/editablePublic.jtd.json`
|
|
12
|
+
* - `schema/readonlyPublic.jtd.json`
|
|
13
|
+
* - `schema/editablePrivate.jtd.json`
|
|
14
|
+
* - `schema/readonlyPrivate.jtd.json`
|
|
15
|
+
* - `schema/system.jtd.json`
|
|
11
16
|
* - `src/`
|
|
17
|
+
* - `schema.json`
|
|
12
18
|
* - `package.json`
|
|
13
19
|
* - `package-lock.json` - *optional*
|
|
14
20
|
* - `yarn.lock` - *optional*
|
|
@@ -30,7 +36,7 @@ async function packProject() {
|
|
|
30
36
|
gzipOptions: { level: 9 },
|
|
31
37
|
});
|
|
32
38
|
archive.on('warning', (err) => {
|
|
33
|
-
if (err
|
|
39
|
+
if (err?.code === 'ENOENT') {
|
|
34
40
|
// lock files and tsconfig may or may not exist
|
|
35
41
|
const fileName = path_1.default.basename(err.path);
|
|
36
42
|
if (fileName === 'package-lock.json' || fileName === 'yarn.lock' || fileName === 'tsconfig.json') {
|
|
@@ -43,6 +49,11 @@ async function packProject() {
|
|
|
43
49
|
handleFailure(err);
|
|
44
50
|
});
|
|
45
51
|
archive.pipe(outputWriteStream);
|
|
52
|
+
archive.file(resolveProjPath('schema/editablePublic.jtd.json'), { name: 'schema/editablePublic.jtd.json' });
|
|
53
|
+
archive.file(resolveProjPath('schema/readonlyPublic.jtd.json'), { name: 'schema/readonlyPublic.jtd.json' });
|
|
54
|
+
archive.file(resolveProjPath('schema/editablePrivate.jtd.json'), { name: 'schema/editablePrivate.jtd.json' });
|
|
55
|
+
archive.file(resolveProjPath('schema/readonlyPrivate.jtd.json'), { name: 'schema/readonlyPrivate.jtd.json' });
|
|
56
|
+
archive.file(resolveProjPath('schema/system.jtd.json'), { name: 'schema/system.jtd.json' });
|
|
46
57
|
archive.file(resolveProjPath('package.json'), { name: 'package.json' });
|
|
47
58
|
archive.file(resolveProjPath('package-lock.json'), { name: 'package-lock.json' });
|
|
48
59
|
archive.file(resolveProjPath('yarn.lock'), { name: 'yarn.lock' });
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const jtd_js_1 = __importDefault(require("ajv/dist/jtd.js"));
|
|
9
|
+
const index_js_1 = __importDefault(require("ajv/dist/standalone/index.js"));
|
|
10
|
+
const schemaNames = ['editablePublic', 'readonlyPublic', 'editablePrivate', 'readonlyPrivate', 'system'];
|
|
11
|
+
async function compileSchema() {
|
|
12
|
+
try {
|
|
13
|
+
const ajv = new jtd_js_1.default({
|
|
14
|
+
// @ts-expect-error: In JTD mode some options are not typed correctly.
|
|
15
|
+
strict: false,
|
|
16
|
+
code: { source: true, esm: true },
|
|
17
|
+
});
|
|
18
|
+
schemaNames.forEach(async (schemaName) => {
|
|
19
|
+
const schemaPath = path_1.default.join(process.cwd(), `./schema/${schemaName}.jtd.json`);
|
|
20
|
+
const schema = await fs_extra_1.default.readJSON(schemaPath);
|
|
21
|
+
ajv.addSchema(schema, schemaName);
|
|
22
|
+
});
|
|
23
|
+
const compiled = ajv.compile(true);
|
|
24
|
+
const moduleCode = (0, index_js_1.default)(ajv, compiled);
|
|
25
|
+
return moduleCode;
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
console.error(e);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.default = compileSchema;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const path_1 = __importDefault(require("path"));
|
|
7
|
+
const tailwindcss_1 = __importDefault(require("tailwindcss"));
|
|
8
|
+
const autoprefixer_1 = __importDefault(require("autoprefixer"));
|
|
9
|
+
const componentLibraryContentPath = path_1.default.join(require.resolve('@linktr.ee/component-library/tailwind.config').split('/').slice(0, -1).join('/'), 'dist', '**', '*.js');
|
|
10
|
+
const uiLinkKitPath = path_1.default.join(require.resolve('@linktr.ee/ui-link-kit').split('/').slice(0, -2).join('/'), '**', '*.js');
|
|
11
|
+
const config = {
|
|
12
|
+
plugins: [
|
|
13
|
+
(0, tailwindcss_1.default)({
|
|
14
|
+
content: [`${process.cwd()}/src/**/*.{js,jsx,ts,tsx}`, componentLibraryContentPath, uiLinkKitPath],
|
|
15
|
+
presets: [require('@linktr.ee/component-library/tailwind.config')],
|
|
16
|
+
plugins: [],
|
|
17
|
+
}),
|
|
18
|
+
(0, autoprefixer_1.default)(),
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
module.exports = config;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--lt-color-primary: #849589;
|
|
3
|
+
--lt-color-on-primary: #ffffff;
|
|
4
|
+
--lt-color-on-primary-alpha: #ffffffb2;
|
|
5
|
+
|
|
6
|
+
--lt-color-secondary: #67776b;
|
|
7
|
+
--lt-color-on-secondary: #ffffffb3;
|
|
8
|
+
|
|
9
|
+
--lt-color-background: #3a463c;
|
|
10
|
+
--lt-color-on-background: #f7fdf9;
|
|
11
|
+
|
|
12
|
+
--lt-color0: #ffffff;
|
|
13
|
+
--lt-color1: #f7fdf9;
|
|
14
|
+
--lt-color2: #eef6ed;
|
|
15
|
+
--lt-color3: #e0ece2;
|
|
16
|
+
--lt-color4: #c9d5cb;
|
|
17
|
+
--lt-color5: #b6c5b7;
|
|
18
|
+
--lt-color6: #849589;
|
|
19
|
+
--lt-color7: #67776b;
|
|
20
|
+
--lt-color8: #4d5e52;
|
|
21
|
+
--lt-color9: #3a463c;
|
|
22
|
+
--lt-color10: #29382d;
|
|
23
|
+
--lt-color11: #151e16;
|
|
24
|
+
--lt-color12: #0b140c;
|
|
25
|
+
--lt-color13: #000501;
|
|
26
|
+
--lt-color14: #000000;
|
|
27
|
+
--lt-color15: #000000;
|
|
28
|
+
|
|
29
|
+
--lt-treetop-radius-mobile: 2.5rem;
|
|
30
|
+
|
|
31
|
+
--lt-cover-radius: 6rem;
|
|
32
|
+
--lt-cover-radius-mobile: 4rem;
|
|
33
|
+
|
|
34
|
+
--lt-feature-container-radius: 2rem;
|
|
35
|
+
--lt-feature-thumbnail-radius: 1.5rem;
|
|
36
|
+
|
|
37
|
+
--lt-carousel-container-radius: 1.5rem;
|
|
38
|
+
--lt-carousel-thumbnail-radius: 1rem;
|
|
39
|
+
|
|
40
|
+
--lt-grid-container-radius: 1.25rem;
|
|
41
|
+
--lt-grid-thumbnail-radius: 0.75rem;
|
|
42
|
+
|
|
43
|
+
--lt-stack-container-radius: 1rem;
|
|
44
|
+
--lt-stack-thumbnail-radius: 0.65rem;
|
|
45
|
+
|
|
46
|
+
--lt-font-family: INTER;
|
|
47
|
+
--lt-text-2xl: 1.5rem;
|
|
48
|
+
--lt-text-xl: 1.25rem;
|
|
49
|
+
--lt-text-lg: 1.125rem;
|
|
50
|
+
--lt-text-md: 1rem;
|
|
51
|
+
--lt-text-sm: 0.875rem;
|
|
52
|
+
--lt-text-xs: 0.75rem;
|
|
53
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
const postcss_1 = __importDefault(require("postcss"));
|
|
30
|
+
const postcssOptions = __importStar(require("../postcss/postcss.config"));
|
|
31
|
+
const config = {
|
|
32
|
+
stories: [`${process.cwd()}/src/**/*.stories.@(js|jsx|ts|tsx)`],
|
|
33
|
+
addons: [
|
|
34
|
+
'@storybook/addon-links',
|
|
35
|
+
'@storybook/addon-essentials',
|
|
36
|
+
{
|
|
37
|
+
name: 'storybook-addon-turbo-build',
|
|
38
|
+
options: {
|
|
39
|
+
optimizationLevel: 2,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
/**
|
|
44
|
+
* Fix Storybook issue with PostCSS@8
|
|
45
|
+
* @see https://github.com/storybookjs/storybook/issues/12668#issuecomment-773958085
|
|
46
|
+
*/
|
|
47
|
+
name: '@storybook/addon-postcss',
|
|
48
|
+
options: {
|
|
49
|
+
cssLoaderOptions: { importLoaders: 1 },
|
|
50
|
+
postcssLoaderOptions: {
|
|
51
|
+
implementation: postcss_1.default,
|
|
52
|
+
postcssOptions: { ...postcssOptions },
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
framework: '@storybook/react',
|
|
58
|
+
core: {
|
|
59
|
+
builder: 'webpack5',
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
module.exports = config;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parameters = void 0;
|
|
4
|
+
require("./global.css");
|
|
5
|
+
exports.parameters = {
|
|
6
|
+
actions: { argTypesRegex: '^on[A-Z].*' },
|
|
7
|
+
controls: {
|
|
8
|
+
matchers: {
|
|
9
|
+
color: /(background|color)$/i,
|
|
10
|
+
date: /Date$/,
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
};
|
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
20
|
+
if (mod && mod.__esModule) return mod;
|
|
21
|
+
var result = {};
|
|
22
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
23
|
+
__setModuleDefault(result, mod);
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
3
26
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
27
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
28
|
};
|
|
@@ -8,18 +31,26 @@ const fork_ts_checker_webpack_plugin_1 = __importDefault(require("fork-ts-checke
|
|
|
8
31
|
const fs_1 = __importDefault(require("fs"));
|
|
9
32
|
const html_webpack_plugin_1 = __importDefault(require("html-webpack-plugin"));
|
|
10
33
|
const inject_body_webpack_plugin_1 = __importDefault(require("inject-body-webpack-plugin"));
|
|
34
|
+
const mini_css_extract_plugin_1 = __importDefault(require("mini-css-extract-plugin"));
|
|
11
35
|
const path_1 = __importDefault(require("path"));
|
|
12
36
|
const webpack_1 = require("webpack");
|
|
13
37
|
const camelcase_1 = __importDefault(require("camelcase"));
|
|
14
38
|
const slugify_1 = __importDefault(require("slugify"));
|
|
39
|
+
const compile_1 = __importDefault(require("../lib/schema/compile"));
|
|
40
|
+
const postcssOptions = __importStar(require("../postcss/postcss.config"));
|
|
15
41
|
const { ModuleFederationPlugin } = webpack_1.container;
|
|
16
|
-
function
|
|
42
|
+
function toVirtualModule(code) {
|
|
43
|
+
const base64 = Buffer.from(code).toString('base64');
|
|
44
|
+
return `data:text/javascript;base64,${base64}`;
|
|
45
|
+
}
|
|
46
|
+
async function default_1(env, options) {
|
|
17
47
|
const appDir = process.cwd();
|
|
18
48
|
const entryFile = path_1.default.resolve(__dirname, `${env}.entry`);
|
|
19
49
|
const htmlTemplateFile = path_1.default.resolve(__dirname, '..', '..', 'html-template', `${env}.html`);
|
|
20
50
|
const manifestJson = JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(appDir, 'manifest.json'), 'utf8'));
|
|
21
51
|
const linkTypeName = manifestJson.name.replace(/[^A-Za-z0-9 ]/g, '');
|
|
22
|
-
const
|
|
52
|
+
const linkTypeSlug = (0, slugify_1.default)(linkTypeName, { lower: true });
|
|
53
|
+
const linkTypeId = (0, camelcase_1.default)(linkTypeSlug, { pascalCase: true });
|
|
23
54
|
const hasTsconfig = fileExists(path_1.default.resolve(appDir, 'tsconfig.json'));
|
|
24
55
|
const config = {
|
|
25
56
|
target: 'web',
|
|
@@ -28,7 +59,9 @@ function default_1(env, options) {
|
|
|
28
59
|
output: {
|
|
29
60
|
publicPath: 'auto',
|
|
30
61
|
path: path_1.default.resolve(appDir, 'dist'),
|
|
31
|
-
assetModuleFilename: 'images/[hash][ext][query]',
|
|
62
|
+
assetModuleFilename: 'images/[hash].[contenthash][ext][query]',
|
|
63
|
+
chunkFilename: '[id].[contenthash].js',
|
|
64
|
+
filename: '[name].[contenthash].js',
|
|
32
65
|
},
|
|
33
66
|
module: {
|
|
34
67
|
rules: [
|
|
@@ -47,7 +80,20 @@ function default_1(env, options) {
|
|
|
47
80
|
},
|
|
48
81
|
{
|
|
49
82
|
test: /\.(png|jpe?g|gif|svg)$/i,
|
|
50
|
-
type: 'asset/inline',
|
|
83
|
+
type: 'asset/inline', // <-- this builds all images into data URLs, is that what you want?
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
test: /\.css$/,
|
|
87
|
+
use: [
|
|
88
|
+
mini_css_extract_plugin_1.default.loader,
|
|
89
|
+
'css-loader',
|
|
90
|
+
{
|
|
91
|
+
loader: 'postcss-loader',
|
|
92
|
+
options: {
|
|
93
|
+
postcssOptions: { ...postcssOptions },
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
],
|
|
51
97
|
},
|
|
52
98
|
],
|
|
53
99
|
},
|
|
@@ -77,6 +123,7 @@ function default_1(env, options) {
|
|
|
77
123
|
...config.resolve.alias,
|
|
78
124
|
'@linktr.ee/extension-dev-data': path_1.default.resolve(appDir, 'fixtures', 'props-data.json'),
|
|
79
125
|
};
|
|
126
|
+
config.plugins.push(new mini_css_extract_plugin_1.default());
|
|
80
127
|
}
|
|
81
128
|
if (env === 'production') {
|
|
82
129
|
// TODO: Figure out how to manage externals with Module Federation
|
|
@@ -104,6 +151,7 @@ function default_1(env, options) {
|
|
|
104
151
|
filename: 'remoteEntry.js',
|
|
105
152
|
exposes: {
|
|
106
153
|
['./App']: path_1.default.resolve(appDir, 'src'),
|
|
154
|
+
['./validate']: toVirtualModule((await (0, compile_1.default)())),
|
|
107
155
|
},
|
|
108
156
|
shared: {
|
|
109
157
|
react: {
|
|
@@ -119,6 +167,9 @@ function default_1(env, options) {
|
|
|
119
167
|
// requiredVersion: '5',
|
|
120
168
|
// },
|
|
121
169
|
},
|
|
170
|
+
}), new mini_css_extract_plugin_1.default({
|
|
171
|
+
filename: '[name].[contenthash].css',
|
|
172
|
+
chunkFilename: '[id].[contenthash].css',
|
|
122
173
|
}));
|
|
123
174
|
}
|
|
124
175
|
return config;
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.3.0-next.
|
|
2
|
+
"version": "0.3.0-next.30",
|
|
3
3
|
"commands": {
|
|
4
4
|
"build": {
|
|
5
5
|
"id": "build",
|
|
@@ -139,6 +139,17 @@
|
|
|
139
139
|
},
|
|
140
140
|
"args": {}
|
|
141
141
|
},
|
|
142
|
+
"generate-types": {
|
|
143
|
+
"id": "generate-types",
|
|
144
|
+
"description": "Generate Typescript types from the schema definitions",
|
|
145
|
+
"strict": true,
|
|
146
|
+
"pluginName": "@linktr.ee/create-link-app",
|
|
147
|
+
"pluginAlias": "@linktr.ee/create-link-app",
|
|
148
|
+
"pluginType": "core",
|
|
149
|
+
"aliases": [],
|
|
150
|
+
"flags": {},
|
|
151
|
+
"args": {}
|
|
152
|
+
},
|
|
142
153
|
"grant-access": {
|
|
143
154
|
"id": "grant-access",
|
|
144
155
|
"description": "Grant access to other developers to push updates for your Link App",
|
|
@@ -216,6 +227,26 @@
|
|
|
216
227
|
}
|
|
217
228
|
},
|
|
218
229
|
"args": {}
|
|
230
|
+
},
|
|
231
|
+
"storybook": {
|
|
232
|
+
"id": "storybook",
|
|
233
|
+
"description": "Start the Storybook development server",
|
|
234
|
+
"strict": true,
|
|
235
|
+
"pluginName": "@linktr.ee/create-link-app",
|
|
236
|
+
"pluginAlias": "@linktr.ee/create-link-app",
|
|
237
|
+
"pluginType": "core",
|
|
238
|
+
"aliases": [],
|
|
239
|
+
"flags": {
|
|
240
|
+
"port": {
|
|
241
|
+
"name": "port",
|
|
242
|
+
"type": "option",
|
|
243
|
+
"char": "p",
|
|
244
|
+
"description": "Port to run the Storybook server on",
|
|
245
|
+
"multiple": false,
|
|
246
|
+
"default": 6006
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
"args": {}
|
|
219
250
|
}
|
|
220
251
|
}
|
|
221
252
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linktr.ee/create-link-app",
|
|
3
|
-
"version": "0.3.0-next.
|
|
3
|
+
"version": "0.3.0-next.30",
|
|
4
4
|
"description": "Create a Link App on Linktr.ee.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "Linktree",
|
|
@@ -19,13 +19,14 @@
|
|
|
19
19
|
"/templates"
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
|
-
"build": "shx rm -rf dist && tsc -b",
|
|
22
|
+
"build": "shx rm -rf dist && tsc -b && yarn copy-storybook-global-css",
|
|
23
23
|
"postpack": "shx rm -f oclif.manifest.json",
|
|
24
24
|
"prepack": "yarn build && oclif manifest && oclif readme",
|
|
25
25
|
"test": "jest --watch",
|
|
26
26
|
"test:ci": "jest",
|
|
27
27
|
"test:cov": "jest --coverage",
|
|
28
|
-
"version": "oclif readme && git add README.md"
|
|
28
|
+
"version": "oclif readme && git add README.md",
|
|
29
|
+
"copy-storybook-global-css": "cp ./src/storybook/global.css ./dist/storybook/global.css"
|
|
29
30
|
},
|
|
30
31
|
"dependencies": {
|
|
31
32
|
"@babel/core": "^7.18.2",
|
|
@@ -34,24 +35,48 @@
|
|
|
34
35
|
"@babel/preset-react": "^7.17.12",
|
|
35
36
|
"@babel/preset-typescript": "^7.17.12",
|
|
36
37
|
"@babel/runtime": "^7.18.3",
|
|
38
|
+
"@linktr.ee/component-library": "^7.0.17",
|
|
39
|
+
"@linktr.ee/ui-link-kit": "latest",
|
|
37
40
|
"@oclif/core": "^1.9.0",
|
|
38
41
|
"@oclif/plugin-help": "^5.1.12",
|
|
42
|
+
"@storybook/addon-actions": "^6.5.9",
|
|
43
|
+
"@storybook/addon-essentials": "^6.5.9",
|
|
44
|
+
"@storybook/addon-interactions": "^6.5.9",
|
|
45
|
+
"@storybook/addon-links": "^6.5.9",
|
|
46
|
+
"@storybook/addon-postcss": "^2.0.0",
|
|
47
|
+
"@storybook/builder-webpack5": "^6.5.9",
|
|
48
|
+
"@storybook/manager-webpack5": "^6.5.9",
|
|
49
|
+
"@storybook/react": "^6.5.9",
|
|
50
|
+
"@tailwindcss/line-clamp": "^0.4.4",
|
|
51
|
+
"@testing-library/react": "^12.1.4",
|
|
52
|
+
"@testing-library/user-event": "14",
|
|
53
|
+
"ajv": "^8.12.0",
|
|
39
54
|
"archiver": "^5.3.1",
|
|
55
|
+
"autoprefixer": "^10.4.14",
|
|
40
56
|
"axios": "^0.27.2",
|
|
41
57
|
"babel-loader": "^8.2.5",
|
|
42
58
|
"camelcase": "^6.3.0",
|
|
59
|
+
"css-loader": "^6.7.3",
|
|
43
60
|
"fork-ts-checker-webpack-plugin": "^7.2.11",
|
|
44
61
|
"form-data": "^4.0.0",
|
|
45
62
|
"fs-extra": "^10.1.0",
|
|
46
63
|
"html-webpack-plugin": "^5.5.0",
|
|
47
64
|
"inject-body-webpack-plugin": "^1.3.0",
|
|
48
65
|
"jsonwebtoken": "^8.5.1",
|
|
66
|
+
"mini-css-extract-plugin": "^2.7.5",
|
|
49
67
|
"netrc-parser": "^3.1.6",
|
|
50
68
|
"openid-client": "^5.1.6",
|
|
69
|
+
"postcss": "^8.4.21",
|
|
70
|
+
"postcss-loader": "^4.3.0",
|
|
71
|
+
"prop-types": "^15.8.1",
|
|
51
72
|
"react": "^17.0.2",
|
|
52
73
|
"react-dom": "^17.0.2",
|
|
53
74
|
"slugify": "^1.6.6",
|
|
75
|
+
"storybook-addon-designs": "^6.3.1",
|
|
76
|
+
"storybook-addon-turbo-build": "^1.1.0",
|
|
77
|
+
"style-loader": "^3.3.2",
|
|
54
78
|
"styled-components": "^5.3.5",
|
|
79
|
+
"tailwindcss": "^3.3.2",
|
|
55
80
|
"typescript": "^4.7.3",
|
|
56
81
|
"webpack": "^5.75.0",
|
|
57
82
|
"webpack-dev-server": "^4.11.1"
|
|
@@ -14,13 +14,34 @@ Optionally, you can specify a different port or serve over HTTPS. Run command wi
|
|
|
14
14
|
|
|
15
15
|
Several files were created during the bootstrapping of this project. Some of these files play a key role:
|
|
16
16
|
|
|
17
|
-
| File
|
|
18
|
-
|
|
|
19
|
-
| `src/index.jsx`
|
|
20
|
-
| `manifest.json`
|
|
21
|
-
| `settings.json`
|
|
22
|
-
| `fixtures/props-data.json` | Used during development, this file acts as mock data for the `settings.json` output, it is injected as props to the entry point component
|
|
23
|
-
| `url-match-rules.json`
|
|
17
|
+
| File | Description |
|
|
18
|
+
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| `src/index.jsx` | The entry point for your Link App |
|
|
20
|
+
| `manifest.json` | Defines key information about your Link App, and helps users to discover your Link App via the [Linktree Marketplace](https://linktr.ee/marketplace) |
|
|
21
|
+
| `settings.json` | Defines the settings made available to Linktree users when configuring the Link App via [Linktree Admin](https://linktr.ee/admin) |
|
|
22
|
+
| `fixtures/props-data.json` | Used during development, this file acts as mock data for the `settings.json` output, it is injected as props to the entry point component |
|
|
23
|
+
| `url-match-rules.json` | Defines the URL pattern to match against when users add a link on Linktree via URL, its structure follows the [URL Pattern API](https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API) |
|
|
24
|
+
| `schema/*.jtd.json` | These files define the shape of the data that is stored for each Link that uses this Link App. They are used to validate the data on the front and back end and to generate Typescript types shared between client and server. The format for these schemas adheres to the [JSON Type Definition](https://jsontypedef.com/), aka [RFC 8927](https://datatracker.ietf.org/doc/html/rfc8927), standard. |
|
|
25
|
+
|
|
26
|
+
## Generating types from your `schema/*.jtd.json` files
|
|
27
|
+
|
|
28
|
+
Under the hood Linktree uses the `jtd-codegen` package to generate types from your schema. If you want to generate types for local development, this package must first be installed on your system. You can install it with the following command:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
brew install jsontypedef/jsontypedef/jtd-codegen
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
You will also require `prettier`
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
brew install prettier
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
When you have these packages installed, you can generate types by running one of the following commands:
|
|
41
|
+
|
|
42
|
+
`npm run generate:types` or `yarn generate:types`
|
|
43
|
+
|
|
44
|
+
For more information on using `jtd-codegen` to generate code see the [official documentation](https://jsontypedef.com/docs/jtd-codegen/), or for specifics on generating Typescript code [here](https://jsontypedef.com/docs/typescript-codegen/).
|
|
24
45
|
|
|
25
46
|
## UI Components
|
|
26
47
|
|
|
@@ -72,18 +93,18 @@ Access to a Link App can be granted to additional users who may need to retrieve
|
|
|
72
93
|
|
|
73
94
|
Please note the user receiving access must also have a Linktree account with developer privileges. Maintainer access can be granted to as many developer accounts as required.
|
|
74
95
|
|
|
75
|
-
|
|
96
|
+
**_Note: Only the Link App Owner can grant Maintainer access to additional users. You must be logged in with an Owner account in order to use the command._**
|
|
76
97
|
|
|
77
98
|
### Maintainer and Owner Permitted Actions
|
|
78
99
|
|
|
79
100
|
The following table compares which actions are permitted for Maintainers and Owners:
|
|
80
101
|
|
|
81
|
-
|Action
|
|
82
|
-
|
|
83
|
-
|Create Link App
|
|
84
|
-
|Get Link App
|
|
85
|
-
|Update Link App
|
|
86
|
-
|Request Link App review
|
|
87
|
-
|Get Link App maintainers
|
|
88
|
-
|Add new Link App maintainer
|
|
89
|
-
|Remove Link App maintainer
|
|
102
|
+
| Action | Owner | Maintainer | Notes |
|
|
103
|
+
| --------------------------- | ------- | ---------- | ----------------------------------------------- |
|
|
104
|
+
| Create Link App | ✓ | N/A | Owner is defined when Link App is first created |
|
|
105
|
+
| Get Link App | ✓ | ✓ | |
|
|
106
|
+
| Update Link App | ✓ | ✓ | |
|
|
107
|
+
| Request Link App review | ✓ | ✓ | |
|
|
108
|
+
| Get Link App maintainers | ✓ | ✓ | |
|
|
109
|
+
| Add new Link App maintainer | ✓ | ✗ | |
|
|
110
|
+
| Remove Link App maintainer | ✓ | ✗ | |
|
|
@@ -1,33 +1,21 @@
|
|
|
1
1
|
{
|
|
2
|
-
"title": "Link
|
|
3
|
-
"overview": {
|
|
4
|
-
"title": "You can have a heading",
|
|
5
|
-
"description": "as well as a description to inform users on what the link does."
|
|
6
|
-
},
|
|
2
|
+
"title": "Link App",
|
|
7
3
|
"elements": [
|
|
8
4
|
{
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"linkBehaviorLabels": {
|
|
14
|
-
"embedLabel": "Embed content on the profile",
|
|
15
|
-
"linkOffLabel": "Go directly to URL"
|
|
16
|
-
},
|
|
17
|
-
"defaultValue": "embedLabel"
|
|
5
|
+
"id": "thumbnailUrl",
|
|
6
|
+
"title": "Thumbnail",
|
|
7
|
+
"inputType": "file",
|
|
8
|
+
"accept": ["image/*"]
|
|
18
9
|
},
|
|
19
10
|
{
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"description": "and describe what the next section of inputs will do",
|
|
24
|
-
"label": "Is feature enabled?",
|
|
25
|
-
"defaultValue": true
|
|
11
|
+
"id": "title",
|
|
12
|
+
"title": "Title",
|
|
13
|
+
"inputType": "text"
|
|
26
14
|
},
|
|
27
15
|
{
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
16
|
+
"id": "url",
|
|
17
|
+
"title": "URL",
|
|
18
|
+
"inputType": "text"
|
|
31
19
|
}
|
|
32
20
|
]
|
|
33
21
|
}
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
"scripts": {
|
|
4
4
|
"build": "create-link-app build",
|
|
5
5
|
"deploy": "create-link-app deploy",
|
|
6
|
-
"
|
|
6
|
+
"storybook": "create-link-app storybook",
|
|
7
|
+
"dev": "create-link-app dev",
|
|
8
|
+
"generate:types": "jtd-codegen ./schema.json --typescript-out src/types --root-name=LinkAppData"
|
|
7
9
|
},
|
|
8
10
|
"devDependencies": {
|
|
9
|
-
"@linktr.ee/
|
|
11
|
+
"@linktr.ee/component-library": "latest",
|
|
12
|
+
"@linktr.ee/create-link-app": "next",
|
|
10
13
|
"@linktr.ee/ui-link-kit": "latest"
|
|
11
14
|
}
|
|
12
15
|
}
|
|
@@ -1,18 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import P from '@linktr.ee/component-library/P'
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import './tailwind.css'
|
|
4
4
|
|
|
5
|
-
function App({
|
|
6
|
-
return
|
|
7
|
-
<Container
|
|
8
|
-
primaryCta={toggle ? { label: 'Visit our UI docs for more info', href: 'https://blstrco.github.io/ui-link-kit/' } : null}
|
|
9
|
-
secondaryCta={toggle ? { label: 'Original url for your Linktree link', href: __linkUrl } : null}
|
|
10
|
-
logo={logo}
|
|
11
|
-
>
|
|
12
|
-
<Header heading={`Hello ${your_name}!`} secondaryHeading="Congratulations, you now have a Linktree link!" layout="hero" />
|
|
13
|
-
<Description>{your_name}</Description>
|
|
14
|
-
</Container>
|
|
15
|
-
)
|
|
5
|
+
function App({ title }) {
|
|
6
|
+
return <P>{title}</P>
|
|
16
7
|
}
|
|
17
8
|
|
|
18
9
|
export default App
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
"scripts": {
|
|
4
4
|
"build": "create-link-app build",
|
|
5
5
|
"deploy": "create-link-app deploy",
|
|
6
|
-
"
|
|
6
|
+
"storybook": "create-link-app storybook",
|
|
7
|
+
"dev": "create-link-app dev",
|
|
8
|
+
"generate:types": "create-link-app generate-types"
|
|
7
9
|
},
|
|
8
10
|
"devDependencies": {
|
|
9
|
-
"@linktr.ee/
|
|
11
|
+
"@linktr.ee/component-library": "latest",
|
|
12
|
+
"@linktr.ee/create-link-app": "next",
|
|
10
13
|
"@linktr.ee/ui-link-kit": "latest",
|
|
11
14
|
"@types/react": "^17.0.0",
|
|
12
15
|
"@types/react-dom": "^17.0.0"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { SettingsData } from '../types'
|
|
2
|
+
|
|
3
|
+
const baseStyle = {
|
|
4
|
+
backgroundColor: 'var(--lt-color-primary)',
|
|
5
|
+
color: 'var(--lt-color-on-primary)',
|
|
6
|
+
} as React.CSSProperties
|
|
7
|
+
|
|
8
|
+
const Featured = (props: SettingsData) => {
|
|
9
|
+
return (
|
|
10
|
+
<div
|
|
11
|
+
className="px-6 pt-12 pb-11 h-full"
|
|
12
|
+
style={{
|
|
13
|
+
...baseStyle,
|
|
14
|
+
borderRadius: 'var(--lt-feature-container-radius)',
|
|
15
|
+
}}
|
|
16
|
+
>
|
|
17
|
+
Featured
|
|
18
|
+
</div>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const Carousel = (props: SettingsData) => {
|
|
23
|
+
return (
|
|
24
|
+
<div
|
|
25
|
+
className="px-4 pt-16 pb-10 h-full"
|
|
26
|
+
style={{
|
|
27
|
+
...baseStyle,
|
|
28
|
+
borderRadius: 'var(--lt-carousel-container-radius)',
|
|
29
|
+
}}
|
|
30
|
+
>
|
|
31
|
+
Carousel
|
|
32
|
+
</div>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const Grid = (props: SettingsData) => {
|
|
37
|
+
return (
|
|
38
|
+
<div className="px-3 py-10 h-full" style={{ ...baseStyle, borderRadius: 'var(--lt-grid-container-radius)' }}>
|
|
39
|
+
Grid
|
|
40
|
+
</div>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const Stack = (props: SettingsData) => {
|
|
45
|
+
return (
|
|
46
|
+
<div className="flex p-2 h-full gap-4 w-full" style={{ ...baseStyle, borderRadius: 'var(--lt-stack-container-radius)' }}>
|
|
47
|
+
<div className="w-16 aspect-square"></div>
|
|
48
|
+
<h2 className="mr-20">Stack</h2>
|
|
49
|
+
</div>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const SheetBody = () => {
|
|
54
|
+
return <div>sheet body</div>
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export { Featured, Carousel, Grid, Stack, SheetBody }
|
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Featured, Carousel, Grid, Stack, SheetBody } from './components/Layouts'
|
|
2
|
+
import { AppProps, Layout } from './types'
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import './tailwind.css'
|
|
5
5
|
|
|
6
|
-
function App(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
6
|
+
function App(props: AppProps) {
|
|
7
|
+
const { layout } = props
|
|
8
|
+
|
|
9
|
+
switch (layout) {
|
|
10
|
+
case Layout.Stack:
|
|
11
|
+
return <Stack {...props} />
|
|
12
|
+
case Layout.Grid:
|
|
13
|
+
return <Grid {...props} />
|
|
14
|
+
case Layout.Carousel:
|
|
15
|
+
return <Carousel {...props} />
|
|
16
|
+
case Layout.Featured:
|
|
17
|
+
return <Featured {...props} />
|
|
18
|
+
case Layout.SheetBody:
|
|
19
|
+
return <SheetBody />
|
|
20
|
+
default:
|
|
21
|
+
return <div>Unknown layout: {props.layout}</div>
|
|
22
|
+
}
|
|
17
23
|
}
|
|
18
24
|
|
|
19
25
|
export default App
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { ComponentStory, ComponentMeta } from '@storybook/react'
|
|
3
|
+
import manifest from '../../manifest.json'
|
|
4
|
+
import fixture from '../../fixtures/props-data.json'
|
|
5
|
+
|
|
6
|
+
import { Layout } from '../types'
|
|
7
|
+
|
|
8
|
+
import LinkApp from '..'
|
|
9
|
+
|
|
10
|
+
import './tailwind.sb.css'
|
|
11
|
+
|
|
12
|
+
export default {
|
|
13
|
+
title: `Link App/${manifest.name}`,
|
|
14
|
+
component: LinkApp,
|
|
15
|
+
tags: ['autodocs'],
|
|
16
|
+
parameters: {
|
|
17
|
+
layout: 'fullscreen',
|
|
18
|
+
},
|
|
19
|
+
args: {
|
|
20
|
+
...fixture,
|
|
21
|
+
editing: false,
|
|
22
|
+
},
|
|
23
|
+
argTypes: {
|
|
24
|
+
layout: {
|
|
25
|
+
table: {
|
|
26
|
+
disable: true,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
} as ComponentMeta<typeof LinkApp>
|
|
31
|
+
|
|
32
|
+
export const Stack: ComponentStory<typeof LinkApp> = (args) => (
|
|
33
|
+
<div
|
|
34
|
+
className="m-2"
|
|
35
|
+
style={{
|
|
36
|
+
width: 374,
|
|
37
|
+
height: 80,
|
|
38
|
+
}}
|
|
39
|
+
>
|
|
40
|
+
<LinkApp {...args} />
|
|
41
|
+
</div>
|
|
42
|
+
)
|
|
43
|
+
Stack.args = {
|
|
44
|
+
layout: Layout.stack,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const Grid: ComponentStory<typeof LinkApp> = (args) => (
|
|
48
|
+
<div
|
|
49
|
+
className="m-2"
|
|
50
|
+
style={{
|
|
51
|
+
width: 183,
|
|
52
|
+
height: 240,
|
|
53
|
+
}}
|
|
54
|
+
>
|
|
55
|
+
<LinkApp {...args} />
|
|
56
|
+
</div>
|
|
57
|
+
)
|
|
58
|
+
Grid.args = {
|
|
59
|
+
layout: Layout.grid,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const Carousel: ComponentStory<typeof LinkApp> = (args) => (
|
|
63
|
+
<div
|
|
64
|
+
className="m-2"
|
|
65
|
+
style={{
|
|
66
|
+
width: 224,
|
|
67
|
+
height: 296,
|
|
68
|
+
}}
|
|
69
|
+
>
|
|
70
|
+
<LinkApp {...args} />
|
|
71
|
+
</div>
|
|
72
|
+
)
|
|
73
|
+
Carousel.args = {
|
|
74
|
+
layout: Layout.carousel,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const Featured: ComponentStory<typeof LinkApp> = (args) => (
|
|
78
|
+
<div
|
|
79
|
+
className="m-2"
|
|
80
|
+
style={{
|
|
81
|
+
width: 374,
|
|
82
|
+
height: 374,
|
|
83
|
+
}}
|
|
84
|
+
>
|
|
85
|
+
<LinkApp {...args} />
|
|
86
|
+
</div>
|
|
87
|
+
)
|
|
88
|
+
Featured.args = {
|
|
89
|
+
layout: Layout.featured,
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const SheetBody: ComponentStory<typeof LinkApp> = (args) => (
|
|
93
|
+
<div className="m-2">
|
|
94
|
+
<LinkApp {...args} />
|
|
95
|
+
</div>
|
|
96
|
+
)
|
|
97
|
+
SheetBody.args = {
|
|
98
|
+
layout: Layout.sheetBody,
|
|
99
|
+
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
declare module '
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
// @HACK: These files are removed at build time, but we need it for type checking
|
|
2
|
+
declare module '*manifest.json' {
|
|
3
|
+
export const name: string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
declare module '*props-data.json' {
|
|
7
|
+
export const name: string
|
|
8
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
type
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export type
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import type { HostData } from '@linktr.ee/ui-link-kit/Schemas'
|
|
2
|
+
import { EditablePrivateData, EditablePublicData, ReadonlyPrivateData, ReadonlyPublicData } from './schema'
|
|
3
|
+
|
|
4
|
+
export type { HostData } from '@linktr.ee/ui-link-kit/Schemas'
|
|
5
|
+
export { HostDataLayout as Layout } from '@linktr.ee/ui-link-kit/Schemas'
|
|
6
|
+
|
|
7
|
+
export type AppProps = HostData & EditablePublicData & ReadonlyPublicData
|
|
8
|
+
export type EditorProps = EditablePublicData & ReadonlyPublicData & EditablePrivateData & ReadonlyPrivateData
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* These types were autogenerated by @linktr.ee/create-link-app
|
|
3
|
+
* https://www.npmjs.com/package/@linktr.ee/create-link-app
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* These are properties that the Linker can `read` and `write`, and the Visitor
|
|
8
|
+
* can `read`
|
|
9
|
+
*/
|
|
10
|
+
export interface EditablePublicData {
|
|
11
|
+
thumbnailUrl: string
|
|
12
|
+
title: string
|
|
13
|
+
url: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* These are properties that the Linker can `read`, and the Visitor can `read`
|
|
18
|
+
*/
|
|
19
|
+
export interface ReadonlyPublicData {}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* These are properties that the Linker can `read`, but the Visitor will never
|
|
23
|
+
* have access to.
|
|
24
|
+
*/
|
|
25
|
+
export interface EditablePrivateData {}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* These are properties that only the Linker can `read`. The Visitor will never
|
|
29
|
+
* have access to these properties
|
|
30
|
+
*/
|
|
31
|
+
export interface ReadonlyPrivateData {
|
|
32
|
+
httpResponseCode: number
|
|
33
|
+
}
|
|
Binary file
|
|
Binary file
|