mirror of
https://github.com/penpot/penpot.git
synced 2025-03-09 14:21:42 -05:00
🎉 Add Storybook to the project
This commit is contained in:
parent
7a33817c22
commit
ebd6cdfe29
15 changed files with 6065 additions and 165 deletions
|
@ -35,6 +35,7 @@ services:
|
|||
- 3447:3447
|
||||
- 3448:3448
|
||||
- 3449:3449
|
||||
- 6006:6006
|
||||
- 6060:6060
|
||||
- 6061:6061
|
||||
- 6062:6062
|
||||
|
|
19
frontend/.storybook/main.js
Normal file
19
frontend/.storybook/main.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
/** @type { import('@storybook/react-vite').StorybookConfig } */
|
||||
const config = {
|
||||
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
|
||||
staticDirs: ["../resources/public"],
|
||||
addons: [
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-essentials",
|
||||
"@storybook/addon-onboarding",
|
||||
"@storybook/addon-interactions",
|
||||
],
|
||||
framework: {
|
||||
name: "@storybook/react-vite",
|
||||
options: {},
|
||||
},
|
||||
docs: {
|
||||
autodocs: "tag",
|
||||
},
|
||||
};
|
||||
export default config;
|
1
frontend/.storybook/preview-head.html
Normal file
1
frontend/.storybook/preview-head.html
Normal file
|
@ -0,0 +1 @@
|
|||
<link href="/css/main.css" rel="stylesheet" type="text/css" />
|
16
frontend/.storybook/preview.js
Normal file
16
frontend/.storybook/preview.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
import "../resources/public/css/main.css";
|
||||
|
||||
/** @type { import('@storybook/react').Preview } */
|
||||
const preview = {
|
||||
parameters: {
|
||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default preview;
|
|
@ -10,13 +10,14 @@ const gulpPostcss = require("gulp-postcss");
|
|||
const gulpRename = require("gulp-rename");
|
||||
const gulpSass = require("gulp-sass")(require("sass"));
|
||||
const svgSprite = require("gulp-svg-sprite");
|
||||
const rename = require("gulp-rename");
|
||||
|
||||
const autoprefixer = require("autoprefixer")
|
||||
const autoprefixer = require("autoprefixer");
|
||||
const modules = require("postcss-modules");
|
||||
|
||||
const clean = require("postcss-clean");
|
||||
const {mkdirp} = require("mkdirp");
|
||||
const {rimraf} = require("rimraf");
|
||||
const { mkdirp } = require("mkdirp");
|
||||
const { rimraf } = require("rimraf");
|
||||
const sass = require("sass");
|
||||
const gettext = require("gettext-parser");
|
||||
const marked = require("marked");
|
||||
|
@ -37,10 +38,10 @@ const touchSourceOnStyleChange = true;
|
|||
const renderer = {
|
||||
link(href, title, text) {
|
||||
return `<a href="${href}" target="_blank">${text}</a>`;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
marked.use({renderer});
|
||||
marked.use({ renderer });
|
||||
|
||||
/***********************************************
|
||||
* Helpers
|
||||
|
@ -49,26 +50,51 @@ marked.use({renderer});
|
|||
// Templates
|
||||
|
||||
function readLocales() {
|
||||
const langs = ["ar", "ca", "de", "el", "en", "eu", "it", "es",
|
||||
"fa", "fr", "he", "nb_NO", "pl", "pt_BR", "ro", "id",
|
||||
"ru", "tr", "zh_CN", "zh_Hant", "hr", "gl", "pt_PT",
|
||||
"cs", "fo", "ko", "lv", "nl",
|
||||
// this happens when file does not matches correct
|
||||
// iso code for the language.
|
||||
["ja_jp", "jpn_JP"],
|
||||
// ["fi", "fin_FI"],
|
||||
["uk", "ukr_UA"]
|
||||
];
|
||||
const langs = [
|
||||
"ar",
|
||||
"ca",
|
||||
"de",
|
||||
"el",
|
||||
"en",
|
||||
"eu",
|
||||
"it",
|
||||
"es",
|
||||
"fa",
|
||||
"fr",
|
||||
"he",
|
||||
"nb_NO",
|
||||
"pl",
|
||||
"pt_BR",
|
||||
"ro",
|
||||
"id",
|
||||
"ru",
|
||||
"tr",
|
||||
"zh_CN",
|
||||
"zh_Hant",
|
||||
"hr",
|
||||
"gl",
|
||||
"pt_PT",
|
||||
"cs",
|
||||
"fo",
|
||||
"ko",
|
||||
"lv",
|
||||
"nl",
|
||||
// this happens when file does not matches correct
|
||||
// iso code for the language.
|
||||
["ja_jp", "jpn_JP"],
|
||||
// ["fi", "fin_FI"],
|
||||
["uk", "ukr_UA"],
|
||||
];
|
||||
const result = {};
|
||||
|
||||
for (let lang of langs) {
|
||||
let filename = `${lang}.po`;
|
||||
if (l.isArray(lang)) {
|
||||
filename = `${lang[1]}.po`;
|
||||
lang = lang[0]
|
||||
lang = lang[0];
|
||||
}
|
||||
|
||||
const content = fs.readFileSync(`./translations/${filename}`, {encoding:"utf-8"});
|
||||
const content = fs.readFileSync(`./translations/${filename}`, { encoding: "utf-8" });
|
||||
|
||||
lang = lang.toLowerCase();
|
||||
|
||||
|
@ -115,46 +141,46 @@ function readLocales() {
|
|||
function readManifest() {
|
||||
try {
|
||||
const path = __dirname + "/resources/public/js/manifest.json";
|
||||
const content = JSON.parse(fs.readFileSync(path, {encoding: "utf8"}));
|
||||
const content = JSON.parse(fs.readFileSync(path, { encoding: "utf8" }));
|
||||
|
||||
const index = {
|
||||
"config": "js/config.js?ts=" + Date.now(),
|
||||
"polyfills": "js/polyfills.js?ts=" + Date.now(),
|
||||
config: "js/config.js?ts=" + Date.now(),
|
||||
polyfills: "js/polyfills.js?ts=" + Date.now(),
|
||||
};
|
||||
|
||||
for (let item of content) {
|
||||
index[item.name] = "js/" + item["output-name"];
|
||||
};
|
||||
}
|
||||
|
||||
return index;
|
||||
} catch (e) {
|
||||
console.error("Error on reading manifest, using default.");
|
||||
return {
|
||||
"config": "js/config.js",
|
||||
"polyfills": "js/polyfills.js",
|
||||
"main": "js/main.js",
|
||||
"shared": "js/shared.js",
|
||||
"worker": "js/worker.js",
|
||||
"rasterizer": "js/rasterizer.js"
|
||||
config: "js/config.js",
|
||||
polyfills: "js/polyfills.js",
|
||||
main: "js/main.js",
|
||||
shared: "js/shared.js",
|
||||
worker: "js/worker.js",
|
||||
rasterizer: "js/rasterizer.js",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function touch() {
|
||||
return mapStream(function(file, cb) {
|
||||
return mapStream(function (file, cb) {
|
||||
if (file.isNull()) {
|
||||
return cb(null, file);
|
||||
}
|
||||
|
||||
// Update file modification and access time
|
||||
return fs.utimes(file.path, new Date(), new Date(), () => {
|
||||
cb(null, file)
|
||||
cb(null, file);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function templatePipeline(options) {
|
||||
return function() {
|
||||
return function () {
|
||||
const input = options.input;
|
||||
const output = options.output;
|
||||
const name = options.name;
|
||||
|
@ -174,11 +200,7 @@ function templatePipeline(options) {
|
|||
themes: JSON.stringify(themes),
|
||||
});
|
||||
|
||||
return gulp.src(input)
|
||||
.pipe(tmpl)
|
||||
.pipe(gulpRename(name))
|
||||
.pipe(gulp.dest(output))
|
||||
.pipe(touch());
|
||||
return gulp.src(input).pipe(tmpl).pipe(gulpRename(name)).pipe(gulp.dest(output)).pipe(touch());
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -188,106 +210,134 @@ function templatePipeline(options) {
|
|||
|
||||
gulpSass.compiler = sass;
|
||||
|
||||
gulp.task("scss:modules", function() {
|
||||
return gulp.src(["src/**/**.scss"])
|
||||
gulp.task("scss:modules", function () {
|
||||
return gulp
|
||||
.src(["src/**/**.scss"])
|
||||
.pipe(cache("sass"))
|
||||
.pipe(gulpSass.sync({includePaths: ["./resources/styles/common/", "./resources/styles/"]}).on('error', gulpSass.logError))
|
||||
.pipe(
|
||||
gulpSass
|
||||
.sync({ includePaths: ["./resources/styles/common/", "./resources/styles/"] })
|
||||
.on("error", gulpSass.logError),
|
||||
)
|
||||
.pipe(cache("modules"))
|
||||
.pipe(gulpPostcss([
|
||||
modules({
|
||||
generateScopedName: "[folder]_[name]_[local]_[hash:base64:5]",
|
||||
}),
|
||||
autoprefixer(),
|
||||
]))
|
||||
.pipe(
|
||||
gulpPostcss([
|
||||
modules({
|
||||
generateScopedName: "[folder]_[name]_[local]_[hash:base64:5]",
|
||||
}),
|
||||
autoprefixer(),
|
||||
]),
|
||||
)
|
||||
.pipe(gulp.dest(paths.output + "css/"));
|
||||
});
|
||||
|
||||
gulp.task("scss:main", function() {
|
||||
return gulp.src(paths.resources + "styles/main-default.scss")
|
||||
.pipe(gulpSass.sync(
|
||||
).on('error', gulpSass.logError))
|
||||
.pipe(gulpPostcss([
|
||||
autoprefixer,
|
||||
]))
|
||||
gulp.task("scss:main", function () {
|
||||
return gulp
|
||||
.src(paths.resources + "styles/main-default.scss")
|
||||
.pipe(gulpSass.sync().on("error", gulpSass.logError))
|
||||
.pipe(gulpPostcss([autoprefixer]))
|
||||
.pipe(gulp.dest(paths.output + "css/"));
|
||||
});
|
||||
|
||||
gulp.task("scss:concat", function() {
|
||||
return gulp.src([paths.output + "css/main-default.css",
|
||||
paths.output + "css/app/**/*.css"])
|
||||
.pipe(gulpConcat("main.css"), {rebaseUrls: false})
|
||||
.pipe(gulp.dest(paths.output + "css/"));
|
||||
gulp.task("scss:concat", function () {
|
||||
return gulp
|
||||
.src([paths.output + "css/main-default.css", paths.output + "css/app/**/*.css"])
|
||||
.pipe(gulpConcat("main.tmp.css"), { rebaseUrls: false })
|
||||
.pipe(gulp.dest(paths.output + ".tmp/"));
|
||||
});
|
||||
|
||||
gulp.task("scss", gulp.series("scss:main", "scss:modules", "scss:concat"));
|
||||
gulp.task("scss:touch", function () {
|
||||
return gulp
|
||||
.src([paths.output + ".tmp/main.tmp.css"])
|
||||
.pipe(rename("main.css"))
|
||||
.pipe(gulp.dest(paths.output + "css/"))
|
||||
.pipe(touch());
|
||||
});
|
||||
|
||||
gulp.task("svg:sprite:icons", function() {
|
||||
return gulp.src(paths.resources + "images/icons/*.svg")
|
||||
.pipe(gulpRename({prefix: "icon-"}))
|
||||
.pipe(svgSprite({mode:{symbol: {inline: true, sprite: "icons.svg"}}}))
|
||||
gulp.task("scss", gulp.series("scss:main", "scss:modules", "scss:concat", "scss:touch"));
|
||||
|
||||
gulp.task("svg:sprite:icons", function () {
|
||||
return gulp
|
||||
.src(paths.resources + "images/icons/*.svg")
|
||||
.pipe(gulpRename({ prefix: "icon-" }))
|
||||
.pipe(svgSprite({ mode: { symbol: { inline: true, sprite: "icons.svg" } } }))
|
||||
.pipe(gulp.dest(paths.output + "images/sprites/"));
|
||||
});
|
||||
|
||||
gulp.task("svg:sprite:cursors", function() {
|
||||
return gulp.src(paths.resources + "images/cursors/*.svg")
|
||||
.pipe(gulpRename({prefix: "cursor-"}))
|
||||
.pipe(svgSprite({mode:{symbol: {inline: true, sprite: "cursors.svg"}}}))
|
||||
gulp.task("svg:sprite:cursors", function () {
|
||||
return gulp
|
||||
.src(paths.resources + "images/cursors/*.svg")
|
||||
.pipe(gulpRename({ prefix: "cursor-" }))
|
||||
.pipe(svgSprite({ mode: { symbol: { inline: true, sprite: "cursors.svg" } } }))
|
||||
.pipe(gulp.dest(paths.output + "images/sprites/"));
|
||||
});
|
||||
|
||||
gulp.task("template:main", templatePipeline({
|
||||
name: "index.html",
|
||||
input: paths.resources + "templates/index.mustache",
|
||||
output: paths.output
|
||||
}));
|
||||
gulp.task(
|
||||
"template:main",
|
||||
templatePipeline({
|
||||
name: "index.html",
|
||||
input: paths.resources + "templates/index.mustache",
|
||||
output: paths.output,
|
||||
}),
|
||||
);
|
||||
|
||||
gulp.task("template:render", templatePipeline({
|
||||
name: "render.html",
|
||||
input: paths.resources + "templates/render.mustache",
|
||||
output: paths.output
|
||||
}));
|
||||
gulp.task(
|
||||
"template:render",
|
||||
templatePipeline({
|
||||
name: "render.html",
|
||||
input: paths.resources + "templates/render.mustache",
|
||||
output: paths.output,
|
||||
}),
|
||||
);
|
||||
|
||||
gulp.task("template:rasterizer", templatePipeline({
|
||||
name: "rasterizer.html",
|
||||
input: paths.resources + "templates/rasterizer.mustache",
|
||||
output: paths.output
|
||||
}));
|
||||
gulp.task(
|
||||
"template:rasterizer",
|
||||
templatePipeline({
|
||||
name: "rasterizer.html",
|
||||
input: paths.resources + "templates/rasterizer.mustache",
|
||||
output: paths.output,
|
||||
}),
|
||||
);
|
||||
|
||||
gulp.task("templates", gulp.series("svg:sprite:icons",
|
||||
"svg:sprite:cursors",
|
||||
"template:main",
|
||||
"template:render",
|
||||
"template:rasterizer"));
|
||||
gulp.task(
|
||||
"templates",
|
||||
gulp.series(
|
||||
"svg:sprite:icons",
|
||||
"svg:sprite:cursors",
|
||||
"template:main",
|
||||
"template:render",
|
||||
"template:rasterizer",
|
||||
),
|
||||
);
|
||||
|
||||
gulp.task("polyfills", function() {
|
||||
return gulp.src(paths.resources + "polyfills/*.js")
|
||||
gulp.task("polyfills", function () {
|
||||
return gulp
|
||||
.src(paths.resources + "polyfills/*.js")
|
||||
.pipe(gulpConcat("polyfills.js"))
|
||||
.pipe(gulp.dest(paths.output + "js/"));
|
||||
});
|
||||
|
||||
gulp.task("copy:assets:images", function() {
|
||||
return gulp.src(paths.resources + "images/**/*")
|
||||
.pipe(gulp.dest(paths.output + "images/"));
|
||||
gulp.task("copy:assets:images", function () {
|
||||
return gulp.src(paths.resources + "images/**/*").pipe(gulp.dest(paths.output + "images/"));
|
||||
});
|
||||
|
||||
gulp.task("copy:assets:fonts", function() {
|
||||
return gulp.src(paths.resources + "fonts/**/*")
|
||||
.pipe(gulp.dest(paths.output + "fonts/"));
|
||||
gulp.task("copy:assets:fonts", function () {
|
||||
return gulp.src(paths.resources + "fonts/**/*").pipe(gulp.dest(paths.output + "fonts/"));
|
||||
});
|
||||
|
||||
gulp.task("copy:assets", gulp.parallel("copy:assets:images", "copy:assets:fonts"));
|
||||
|
||||
gulp.task("dev:dirs", async function(next) {
|
||||
gulp.task("dev:dirs", async function (next) {
|
||||
await mkdirp("./resources/public/css/");
|
||||
await mkdirp("./resources/public/js/");
|
||||
next();
|
||||
});
|
||||
|
||||
gulp.task("watch:main", function() {
|
||||
gulp.task("watch:main", function () {
|
||||
const watchTask = gulp.watch("src/**/**.scss", gulp.series("scss"));
|
||||
|
||||
if (touchSourceOnStyleChange) {
|
||||
watchTask.on("change", function(path) {
|
||||
watchTask.on("change", function (path) {
|
||||
// Replace ".scss" for ".cljs" to refresh the file
|
||||
gulp.src(path.replace(".scss", ".cljs")).pipe(touch());
|
||||
});
|
||||
|
@ -296,16 +346,14 @@ gulp.task("watch:main", function() {
|
|||
gulp.watch(paths.resources + "styles/**/**.scss", gulp.series("scss"));
|
||||
gulp.watch(paths.resources + "images/**/*", gulp.series("copy:assets:images"));
|
||||
|
||||
gulp.watch([paths.resources + "templates/*.mustache",
|
||||
"translations/*.po"],
|
||||
gulp.series("templates"));
|
||||
gulp.watch([paths.resources + "templates/*.mustache", "translations/*.po"], gulp.series("templates"));
|
||||
});
|
||||
|
||||
gulp.task("clean:output", function(next) {
|
||||
rimraf(paths.output).finally(next)
|
||||
gulp.task("clean:output", function (next) {
|
||||
rimraf(paths.output).finally(next);
|
||||
});
|
||||
|
||||
gulp.task("clean:dist", function(next) {
|
||||
gulp.task("clean:dist", function (next) {
|
||||
rimraf(paths.dist).finally(next);
|
||||
});
|
||||
|
||||
|
@ -314,7 +362,6 @@ gulp.task("build:assets", gulp.parallel("polyfills", "templates", "copy:assets")
|
|||
|
||||
gulp.task("watch", gulp.series("dev:dirs", "build:styles", "build:assets", "watch:main"));
|
||||
|
||||
gulp.task("build:copy", function() {
|
||||
return gulp.src(paths.output + "**/*")
|
||||
.pipe(gulp.dest(paths.dist));
|
||||
gulp.task("build:copy", function () {
|
||||
return gulp.src(paths.output + "**/*").pipe(gulp.dest(paths.dist));
|
||||
});
|
||||
|
|
|
@ -27,9 +27,19 @@
|
|||
"build:clean": "gulp clean:output && gulp clean:dist",
|
||||
"build:styles": "gulp build:styles",
|
||||
"build:assets": "gulp build:assets",
|
||||
"build:copy": "gulp build:copy"
|
||||
"build:copy": "gulp build:copy",
|
||||
"storybook": "storybook dev -p 6006",
|
||||
"build-storybook": "storybook build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-essentials": "^7.5.3",
|
||||
"@storybook/addon-interactions": "^7.5.3",
|
||||
"@storybook/addon-links": "^7.5.3",
|
||||
"@storybook/addon-onboarding": "^1.0.8",
|
||||
"@storybook/blocks": "^7.5.3",
|
||||
"@storybook/react": "^7.5.3",
|
||||
"@storybook/react-vite": "^7.5.3",
|
||||
"@storybook/testing-library": "^0.2.2",
|
||||
"autoprefixer": "^10.4.15",
|
||||
"cypress": "^10.3.0",
|
||||
"cypress-file-upload": "^5.0.8",
|
||||
|
@ -52,9 +62,12 @@
|
|||
"postcss": "^8.4.29",
|
||||
"postcss-clean": "^1.2.2",
|
||||
"prettier": "^3.0.3",
|
||||
"prop-types": "^15.8.1",
|
||||
"rimraf": "^5.0.1",
|
||||
"sass": "^1.66.1",
|
||||
"shadow-cljs": "2.25.10"
|
||||
"shadow-cljs": "2.25.10",
|
||||
"storybook": "^7.5.3",
|
||||
"vite": "^5.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sentry/browser": "^6.17.4",
|
||||
|
|
|
@ -53,9 +53,23 @@
|
|||
:anon-fn-naming-policy :off
|
||||
:source-map-detail-level :all}}}
|
||||
|
||||
:lib-penpot
|
||||
:storybook
|
||||
{:target :esm
|
||||
:output-dir "resources/public/libs"
|
||||
:output-dir "target/storybook/"
|
||||
:modules
|
||||
{:design-system {:exports {default app.main.ui.components.design-system/default} }}
|
||||
|
||||
:js-options
|
||||
{:js-provider :import}
|
||||
|
||||
:compiler-options
|
||||
{:output-feature-set :es2020
|
||||
:output-wrapper false
|
||||
:warnings {:fn-deprecated false}}}
|
||||
|
||||
:lib-penpot
|
||||
{:target :esm
|
||||
:output-dir "resources/public/libs"
|
||||
|
||||
:modules
|
||||
{:penpot {:exports {:renderPage app.libs.render/render-page-export
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
(ns app.main.ui.components.buttons.simple-button
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc simple-button
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [on-click children]}]
|
||||
[:button {:on-click on-click :class (dm/str (stl/css :button))} children])
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import { Canvas, Meta } from '@storybook/blocks';
|
||||
import * as SimpleButtonStories from "./simple_button.stories"
|
||||
|
||||
<Meta of={SimpleButtonStories} />
|
||||
|
||||
# Lorem ipsum
|
||||
|
||||
This is an example of **markdown** docs within storybook, for the component `<SimpleButton>`.
|
||||
|
||||
Here's how we can render a simple button:
|
||||
|
||||
<Canvas of={SimpleButtonStories.Default} />
|
||||
|
||||
Simple buttons can also have **icons**:
|
||||
|
||||
<Canvas of={SimpleButtonStories.WithIcon} />
|
|
@ -0,0 +1,13 @@
|
|||
.button {
|
||||
font-family: monospace;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
column-gap: 0.5rem;
|
||||
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
stroke: #000;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
import * as React from "react";
|
||||
|
||||
import ds from "@target/design-system";
|
||||
|
||||
const { SimpleButton, StoryWrapper, icons } = ds;
|
||||
|
||||
export default {
|
||||
title: 'Buttons/Simple Button',
|
||||
component: SimpleButton,
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
render: () => (
|
||||
<StoryWrapper>
|
||||
<SimpleButton>
|
||||
Simple Button
|
||||
</SimpleButton>
|
||||
</StoryWrapper>
|
||||
),
|
||||
};
|
||||
|
||||
export const WithIcon = {
|
||||
render: () => (
|
||||
<StoryWrapper>
|
||||
<SimpleButton>
|
||||
{icons.IconAddRefactor}
|
||||
Simple Button
|
||||
</SimpleButton>
|
||||
</StoryWrapper>
|
||||
),
|
||||
}
|
17
frontend/src/app/main/ui/components/design_system.cljs
Normal file
17
frontend/src/app/main/ui/components/design_system.cljs
Normal file
|
@ -0,0 +1,17 @@
|
|||
(ns app.main.ui.components.design-system
|
||||
(:require
|
||||
[app.main.ui.components.buttons.simple-button :as sb]
|
||||
[app.main.ui.icons :as icons]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc story-wrapper
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [children]}]
|
||||
[:.default children])
|
||||
|
||||
(def ^export default #js {
|
||||
:icons #js {
|
||||
:IconAddRefactor icons/add-refactor
|
||||
}
|
||||
:StoryWrapper story-wrapper
|
||||
:SimpleButton sb/simple-button})
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
(defmacro icon-xref
|
||||
[id]
|
||||
(let [href (str "#icon-" (name id))
|
||||
(let [href (str "/images/sprites/symbol/icons.svg#icon-" (name id))
|
||||
class (str "icon-" (name id))]
|
||||
`(rumext.v2/html
|
||||
[:svg {:width 500 :height 500 :class ~class}
|
||||
|
|
11
frontend/vite.config.js
Normal file
11
frontend/vite.config.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { defineConfig } from "vite";
|
||||
import { resolve } from "path";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
"@target": resolve(__dirname, "./target/storybook"),
|
||||
},
|
||||
},
|
||||
});
|
5800
frontend/yarn.lock
5800
frontend/yarn.lock
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue