poveste 0.13.0 → 0.14.0
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/client.d.ts +9 -1
- package/dist/node/build-counts.d.ts +26 -0
- package/dist/node/build-counts.js +31 -0
- package/dist/node/build.js +6 -6
- package/dist/node/collect/index.js +2 -1
- package/dist/node/virtual/codegen.d.ts +22 -0
- package/dist/node/virtual/codegen.js +30 -0
- package/dist/node/virtual/resolved-commands.js +3 -2
- package/dist/node/virtual/resolved-config.js +3 -2
- package/dist/node/virtual/resolved-stories.js +2 -1
- package/dist/node/virtual/resolved-support-plugins-client.js +2 -1
- package/dist/node/virtual/resolved-support-plugins-collect.js +2 -1
- package/dist/node/virtual/util.js +2 -1
- package/dist/node/vite.js +4 -3
- package/package.json +6 -6
- package/plugin.d.ts +11 -0
- package/plugin.js +5 -0
- package/dist/node/builtin-plugins/pinceau-tokens-style.d.ts +0 -1
- package/dist/node/builtin-plugins/pinceau-tokens-style.js +0 -85
- package/dist/node/builtin-plugins/pinceau-tokens.d.ts +0 -6
- package/dist/node/builtin-plugins/pinceau-tokens.js +0 -424
package/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @deprecated
|
|
2
|
+
* @deprecated Use {@link logEvent} instead. This forwards to it and warns.
|
|
3
3
|
*/
|
|
4
4
|
export function hstEvent(name: string, argument): void
|
|
5
5
|
|
|
@@ -15,5 +15,13 @@ export function logEvent(name: string, argument): void
|
|
|
15
15
|
*/
|
|
16
16
|
export function isCollecting(): boolean
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Switches the book between light and dark, or to `value` when one is given.
|
|
20
|
+
* Returns the mode it ended up in.
|
|
21
|
+
*/
|
|
18
22
|
export function toggleDark(value?: boolean): boolean
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Whether the book is currently in dark mode.
|
|
26
|
+
*/
|
|
19
27
|
export function isDark(): boolean
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ServerStoryFile } from '@poveste/shared';
|
|
2
|
+
export interface BuildCounts {
|
|
3
|
+
/** Story files that produced a story with variants. */
|
|
4
|
+
stories: number;
|
|
5
|
+
variants: number;
|
|
6
|
+
/** Standalone `.story.md` pages, which the book's home page calls Documents. */
|
|
7
|
+
docs: number;
|
|
8
|
+
/** Relative paths of the files that produced neither, so the warning can name them. */
|
|
9
|
+
empty: string[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Splits the collected story files three ways, the way the book's own home page
|
|
13
|
+
* does: stories, documents, and files that produced nothing.
|
|
14
|
+
*
|
|
15
|
+
* "No variants" is not the question. A standalone `.story.md` is collected into a
|
|
16
|
+
* story with `docsOnly: true` and `variants: []` by construction (`markdown.ts`),
|
|
17
|
+
* so counting empty by variants alone reported every documentation page in the
|
|
18
|
+
* book as a problem — three of the four `examples/vue3` warned about are
|
|
19
|
+
* `SHARED_STORY_TITLES` entries that a required spec fails if you delete them,
|
|
20
|
+
* which left the one real empty file hidden inside them (#670).
|
|
21
|
+
*
|
|
22
|
+
* Documents are counted rather than folded in with stories because `HomeView.vue`
|
|
23
|
+
* already makes exactly this split, and a build that reports 60 stories over a
|
|
24
|
+
* home page reading 57 Stories and 3 Documents disagrees with itself.
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildCounts(storyFiles: ServerStoryFile[]): BuildCounts;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Splits the collected story files three ways, the way the book's own home page
|
|
3
|
+
* does: stories, documents, and files that produced nothing.
|
|
4
|
+
*
|
|
5
|
+
* "No variants" is not the question. A standalone `.story.md` is collected into a
|
|
6
|
+
* story with `docsOnly: true` and `variants: []` by construction (`markdown.ts`),
|
|
7
|
+
* so counting empty by variants alone reported every documentation page in the
|
|
8
|
+
* book as a problem — three of the four `examples/vue3` warned about are
|
|
9
|
+
* `SHARED_STORY_TITLES` entries that a required spec fails if you delete them,
|
|
10
|
+
* which left the one real empty file hidden inside them (#670).
|
|
11
|
+
*
|
|
12
|
+
* Documents are counted rather than folded in with stories because `HomeView.vue`
|
|
13
|
+
* already makes exactly this split, and a build that reports 60 stories over a
|
|
14
|
+
* home page reading 57 Stories and 3 Documents disagrees with itself.
|
|
15
|
+
*/
|
|
16
|
+
export function buildCounts(storyFiles) {
|
|
17
|
+
const counts = { stories: 0, variants: 0, docs: 0, empty: [] };
|
|
18
|
+
for (const file of storyFiles) {
|
|
19
|
+
if (file.story?.docsOnly) {
|
|
20
|
+
counts.docs++;
|
|
21
|
+
}
|
|
22
|
+
else if (file.story?.variants.length) {
|
|
23
|
+
counts.stories++;
|
|
24
|
+
counts.variants += file.story.variants.length;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
counts.empty.push(file.relativePath);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return counts;
|
|
31
|
+
}
|
package/dist/node/build.js
CHANGED
|
@@ -5,6 +5,7 @@ import { join } from 'pathe';
|
|
|
5
5
|
import pc from 'picocolors';
|
|
6
6
|
import { createServer as createViteServer, mergeConfig as mergeViteConfig, build as viteBuild, } from 'vite';
|
|
7
7
|
import { APP_PATH } from './alias.js';
|
|
8
|
+
import { buildCounts } from './build-counts.js';
|
|
8
9
|
import { getSerializedStoryData } from './build-serialize.js';
|
|
9
10
|
import { useCollectStories } from './collect/index.js';
|
|
10
11
|
import { useModuleLoader } from './load.js';
|
|
@@ -105,9 +106,7 @@ export async function build(ctx) {
|
|
|
105
106
|
// Same wrapper the dev path uses for these exact calls (server.ts).
|
|
106
107
|
await wrapLogError('destroyCollectStories', () => destroyCollectStories());
|
|
107
108
|
}
|
|
108
|
-
const storyCount
|
|
109
|
-
const variantCount = ctx.storyFiles.reduce((sum, file) => sum + (file.story?.variants.length ?? 0), 0);
|
|
110
|
-
const emptyStoryCount = ctx.storyFiles.length - storyCount;
|
|
109
|
+
const { stories: storyCount, variants: variantCount, docs: docsCount, empty } = buildCounts(ctx.storyFiles);
|
|
111
110
|
const { viteConfig: buildViteConfigRaw } = await getViteConfigWithPlugins(false, ctx);
|
|
112
111
|
const buildViteConfig = mergeViteConfig(buildViteConfigRaw, {
|
|
113
112
|
// Vite picks the `.env` file from `mode`, not from NODE_ENV — this said
|
|
@@ -261,10 +260,11 @@ export async function build(ctx) {
|
|
|
261
260
|
await writeFile('__sandbox.html', sandboxHtml, ctx);
|
|
262
261
|
await writeFile('poveste.json', JSON.stringify(getSerializedStoryData(ctx), null, 2), ctx);
|
|
263
262
|
const duration = performance.now() - startTime;
|
|
264
|
-
if (
|
|
265
|
-
console.warn(pc.yellow(`⚠️ ${
|
|
263
|
+
if (empty.length) {
|
|
264
|
+
console.warn(pc.yellow(`⚠️ ${empty.length} empty story file${empty.length === 1 ? '' : 's'}: ${empty.join(', ')}`));
|
|
266
265
|
}
|
|
267
|
-
|
|
266
|
+
const docsNote = docsCount ? ` and ${docsCount} document${docsCount === 1 ? '' : 's'}` : '';
|
|
267
|
+
console.log(pc.green(`✅ Built ${storyCount} stor${storyCount === 1 ? 'y' : 'ies'} (${variantCount} variant${variantCount === 1 ? '' : 's'})${docsNote} in ${Math.round(duration / 1000 * 100) / 100}s`));
|
|
268
268
|
// Render
|
|
269
269
|
if (previewStoryCallbacks.length) {
|
|
270
270
|
const { baseUrl, close } = await startPreview({}, ctx);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cpus } from 'node:os';
|
|
2
2
|
import { MessageChannel } from 'node:worker_threads';
|
|
3
3
|
import Tinypool from '@akryum/tinypool';
|
|
4
|
+
import { escapeRegExp } from '@poveste/shared';
|
|
4
5
|
import { createBirpc } from 'birpc';
|
|
5
6
|
import path, { relative } from 'pathe';
|
|
6
7
|
import pc from 'picocolors';
|
|
@@ -29,7 +30,7 @@ export function useCollectStories(options, ctx) {
|
|
|
29
30
|
// @TODO temporary fix for https://github.com/histoire-dev/histoire/issues/409
|
|
30
31
|
/vite\w*\/dist\/client\/(client|env).mjs/,
|
|
31
32
|
...ctx.config.viteNodeInlineDeps ?? [],
|
|
32
|
-
new RegExp(path.resolve(TEMP_PATH, 'plugins')),
|
|
33
|
+
new RegExp(escapeRegExp(path.resolve(TEMP_PATH, 'plugins'))),
|
|
33
34
|
],
|
|
34
35
|
fallbackCJS: true,
|
|
35
36
|
},
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emitting values into generated modules.
|
|
3
|
+
*
|
|
4
|
+
* Every generator in this directory builds JavaScript source by interpolation,
|
|
5
|
+
* and most of the values come from somewhere the author of that source did not
|
|
6
|
+
* control — a plugin's id, a user's config key, the project's own path. Getting
|
|
7
|
+
* it wrong produces a syntax error inside a module nobody wrote and nobody can
|
|
8
|
+
* open, which is the symptom rather than a crash at the input (#609).
|
|
9
|
+
*
|
|
10
|
+
* There are two positions and they need different things.
|
|
11
|
+
*/
|
|
12
|
+
/** A value in a string or key position. Valid JSON is valid JavaScript here. */
|
|
13
|
+
export declare function jsString(value: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* A value in an *identifier* position — a binding name, an import name.
|
|
16
|
+
*
|
|
17
|
+
* Quoting cannot help here, so the only honest options are to reject the value
|
|
18
|
+
* or to rename it. These names are read back by consumers (`logos.square`,
|
|
19
|
+
* `generatedSetup.setupVue3`), so renaming would move the problem to whoever
|
|
20
|
+
* looks them up. It rejects, naming the value and where it came from.
|
|
21
|
+
*/
|
|
22
|
+
export declare function jsIdentifier(value: string, what: string): string;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emitting values into generated modules.
|
|
3
|
+
*
|
|
4
|
+
* Every generator in this directory builds JavaScript source by interpolation,
|
|
5
|
+
* and most of the values come from somewhere the author of that source did not
|
|
6
|
+
* control — a plugin's id, a user's config key, the project's own path. Getting
|
|
7
|
+
* it wrong produces a syntax error inside a module nobody wrote and nobody can
|
|
8
|
+
* open, which is the symptom rather than a crash at the input (#609).
|
|
9
|
+
*
|
|
10
|
+
* There are two positions and they need different things.
|
|
11
|
+
*/
|
|
12
|
+
/** A value in a string or key position. Valid JSON is valid JavaScript here. */
|
|
13
|
+
export function jsString(value) {
|
|
14
|
+
return JSON.stringify(value);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A value in an *identifier* position — a binding name, an import name.
|
|
18
|
+
*
|
|
19
|
+
* Quoting cannot help here, so the only honest options are to reject the value
|
|
20
|
+
* or to rename it. These names are read back by consumers (`logos.square`,
|
|
21
|
+
* `generatedSetup.setupVue3`), so renaming would move the problem to whoever
|
|
22
|
+
* looks them up. It rejects, naming the value and where it came from.
|
|
23
|
+
*/
|
|
24
|
+
export function jsIdentifier(value, what) {
|
|
25
|
+
if (!/^[A-Z_$][\w$]*$/i.test(value)) {
|
|
26
|
+
throw new Error(`${what} must be usable as a JavaScript identifier, and ${JSON.stringify(value)} is not. `
|
|
27
|
+
+ 'It is emitted into a generated module as a binding name, where quoting cannot rescue it.');
|
|
28
|
+
}
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { jsIdentifier, jsString } from './codegen.js';
|
|
1
2
|
const serializedFields = ['id', 'label', 'prompts', 'icon', 'searchText'];
|
|
2
3
|
export function resolvedCommands(ctx) {
|
|
3
4
|
const imports = [];
|
|
@@ -21,10 +22,10 @@ function getCommandFields(command, imports) {
|
|
|
21
22
|
if (command.clientSetupFile) {
|
|
22
23
|
const importedVar = `__setup${imports.length}__`;
|
|
23
24
|
if (typeof command.clientSetupFile === 'string') {
|
|
24
|
-
imports.push(`import ${importedVar} from
|
|
25
|
+
imports.push(`import ${importedVar} from ${jsString(command.clientSetupFile)}`);
|
|
25
26
|
}
|
|
26
27
|
else {
|
|
27
|
-
imports.push(`import { ${command.clientSetupFile.importName} as ${importedVar} } from
|
|
28
|
+
imports.push(`import { ${jsIdentifier(command.clientSetupFile.importName, `clientSetupFile.importName '${command.clientSetupFile.importName}'`)} as ${importedVar} } from ${jsString(command.clientSetupFile.file)}`);
|
|
28
29
|
}
|
|
29
30
|
fields.push(`...${importedVar}`);
|
|
30
31
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { jsIdentifier, jsString } from './codegen.js';
|
|
1
2
|
export function resolvedConfig(ctx) {
|
|
2
3
|
let js = `export const config = ${JSON.stringify(ctx.config)}\n`;
|
|
3
4
|
if (ctx.config.theme?.logo) {
|
|
4
5
|
for (const key in ctx.config.theme.logo) {
|
|
5
|
-
js += `import Logo_${key} from
|
|
6
|
+
js += `import Logo_${jsIdentifier(key, `theme.logo key '${key}'`)} from ${jsString(ctx.config.theme.logo[key])}\n`;
|
|
6
7
|
}
|
|
7
8
|
}
|
|
8
|
-
js += `export const logos = {${Object.keys(ctx.config.theme?.logo ?? {}).map(key => `${key}: Logo_${key}`).join(', ')}}\n`;
|
|
9
|
+
js += `export const logos = {${Object.keys(ctx.config.theme?.logo ?? {}).map(key => `${jsString(key)}: Logo_${key}`).join(', ')}}\n`;
|
|
9
10
|
return js;
|
|
10
11
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { makeTree } from '../tree.js';
|
|
2
|
+
import { jsString } from './codegen.js';
|
|
2
3
|
export function resolvedStories(ctx) {
|
|
3
4
|
const resolvedStories = ctx.storyFiles.filter(s => !!s.story);
|
|
4
5
|
const files = resolvedStories.map((file, index) => {
|
|
@@ -23,7 +24,7 @@ ${resolvedStories.map((file, index) => {
|
|
|
23
24
|
}
|
|
24
25
|
return supportPlugin.importStoryComponent(file, index);
|
|
25
26
|
}).filter(Boolean).join('\n')}
|
|
26
|
-
export let files = [${files.map(file => `{${JSON.stringify(file).slice(1, -1)}, component: Comp${file.index}, source: () => import(
|
|
27
|
+
export let files = [${files.map(file => `{${JSON.stringify(file).slice(1, -1)}, component: Comp${file.index}, source: () => import(${jsString(`virtual:story-source:${file.story.id}`)})}`).join(',\n')}]
|
|
27
28
|
export let tree = ${JSON.stringify(makeTree(ctx.config, resolvedStories))}
|
|
28
29
|
const handlers = []
|
|
29
30
|
export function onUpdate (cb) {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
|
+
import { jsString } from './codegen.js';
|
|
2
3
|
import { PLUGINS_HAVE_DEV } from './util.js';
|
|
3
4
|
const require = createRequire(import.meta.url);
|
|
4
5
|
export function resolvedSupportPluginsClient(ctx) {
|
|
5
|
-
const plugins = ctx.supportPlugins.map(p =>
|
|
6
|
+
const plugins = ctx.supportPlugins.map(p => `${jsString(p.id)}: () => import(${JSON.stringify(require.resolve(`${p.moduleName}/client${process.env.POVESTE_DEV && PLUGINS_HAVE_DEV.includes(p.moduleName) ? '-dev' : ''}`, {
|
|
6
7
|
paths: [ctx.root, import.meta.url],
|
|
7
8
|
}))})`);
|
|
8
9
|
return `export const clientSupportPlugins = {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
|
+
import { jsString } from './codegen.js';
|
|
2
3
|
import { PLUGINS_HAVE_DEV } from './util.js';
|
|
3
4
|
const require = createRequire(import.meta.url);
|
|
4
5
|
export function resolvedSupportPluginsCollect(ctx) {
|
|
5
|
-
const plugins = ctx.supportPlugins.map(p =>
|
|
6
|
+
const plugins = ctx.supportPlugins.map(p => `${jsString(p.id)}: () => import(${JSON.stringify(require.resolve(`${p.moduleName}/collect${process.env.POVESTE_DEV && PLUGINS_HAVE_DEV.includes(p.moduleName) ? '-dev' : ''}`, {
|
|
6
7
|
paths: [ctx.root, import.meta.url],
|
|
7
8
|
}))})`);
|
|
8
9
|
return `export const collectSupportPlugins = {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { jsIdentifier } from './codegen.js';
|
|
1
2
|
export const ID_SEPARATOR = '__-__';
|
|
2
3
|
/**
|
|
3
4
|
* Names of every setup hook contributed by the enabled support plugins, e.g.
|
|
@@ -28,7 +29,7 @@ export function getSetupFnGroups(ctx) {
|
|
|
28
29
|
* in every consumer build.
|
|
29
30
|
*/
|
|
30
31
|
export function declareEmptySetupFns(ctx) {
|
|
31
|
-
return getSetupFnNames(ctx).map(fnName => `export const ${fnName} = undefined`).join('\n');
|
|
32
|
+
return getSetupFnNames(ctx).map(fnName => `export const ${jsIdentifier(fnName, `support plugin setupFn '${fnName}'`)} = undefined`).join('\n');
|
|
32
33
|
}
|
|
33
34
|
export const PLUGINS_HAVE_DEV = [
|
|
34
35
|
'@poveste/plugin-vue',
|
package/dist/node/vite.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
+
import { escapeRegExp } from '@poveste/shared';
|
|
3
4
|
import { lookup as lookupMime } from 'mrmime';
|
|
4
5
|
import { dirname, join, relative } from 'pathe';
|
|
5
6
|
import { loadConfigFromFile as loadViteConfigFromFile, mergeConfig as mergeViteConfig, searchForWorkspaceRoot, } from 'vite';
|
|
@@ -299,7 +300,7 @@ export async function getViteConfigWithPlugins(isServer, ctx) {
|
|
|
299
300
|
if (/\.(?:vue|js)(?:$|\?)/.test(id)) {
|
|
300
301
|
const original = code;
|
|
301
302
|
for (const flag in flags) {
|
|
302
|
-
code = code.replace(new RegExp(flag, 'g'), flags[flag]);
|
|
303
|
+
code = code.replace(new RegExp(escapeRegExp(flag), 'g'), flags[flag]);
|
|
303
304
|
}
|
|
304
305
|
if (original !== code)
|
|
305
306
|
return code;
|
|
@@ -360,11 +361,11 @@ export async function getViteConfigWithPlugins(isServer, ctx) {
|
|
|
360
361
|
['vue', 'vue'],
|
|
361
362
|
].reduce((acc, [name, entry]) => {
|
|
362
363
|
acc.push({
|
|
363
|
-
find: new RegExp(`^${name
|
|
364
|
+
find: new RegExp(`^${escapeRegExp(name)}$`),
|
|
364
365
|
replacement: `@poveste/vendors/${entry}`,
|
|
365
366
|
});
|
|
366
367
|
acc.push({
|
|
367
|
-
find: new RegExp(`^${name
|
|
368
|
+
find: new RegExp(`^${escapeRegExp(name)}/`),
|
|
368
369
|
replacement: `@poveste/vendors/${entry}/`,
|
|
369
370
|
});
|
|
370
371
|
return acc;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "poveste",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.14.0",
|
|
5
5
|
"description": "Interactive component playgrounds for Vue, Nuxt, Svelte, SvelteKit and Quasar — a drop-in fork of histoire, with Quasar support histoire does not ship.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Sorin Gitlan",
|
|
@@ -73,10 +73,10 @@
|
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
75
|
"@akryum/tinypool": "^0.3.1",
|
|
76
|
-
"@poveste/app": "^0.
|
|
77
|
-
"@poveste/controls": "^0.
|
|
78
|
-
"@poveste/shared": "^0.
|
|
79
|
-
"@poveste/vendors": "^0.
|
|
76
|
+
"@poveste/app": "^0.14.0",
|
|
77
|
+
"@poveste/controls": "^0.14.0",
|
|
78
|
+
"@poveste/shared": "^0.14.0",
|
|
79
|
+
"@poveste/vendors": "^0.14.0",
|
|
80
80
|
"@types/markdown-it": "^14.1.2",
|
|
81
81
|
"birpc": "^0.2.19",
|
|
82
82
|
"change-case": "^5.4.4",
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
"@types/node": "^22.10.1",
|
|
110
110
|
"typescript": "5.6.3",
|
|
111
111
|
"vite": "^8.2.0",
|
|
112
|
-
"vitest": "^
|
|
112
|
+
"vitest": "^5.0.0"
|
|
113
113
|
},
|
|
114
114
|
"scripts": {
|
|
115
115
|
"build": "rimraf dist && tsc",
|
package/plugin.d.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sends a custom event from the book UI to the plugin's `onDevEvent` hook, and
|
|
3
|
+
* resolves with whatever that hook returns.
|
|
4
|
+
*
|
|
5
|
+
* Development only: the API it calls is installed by the dev server, so in a
|
|
6
|
+
* built book this resolves to `undefined` without erroring.
|
|
7
|
+
*/
|
|
1
8
|
export function sendEvent(event: string, payload?: any): Promise<any>
|
|
2
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Navigates the book to a story by its `id` — the same field `getStories()`
|
|
12
|
+
* returns on the plugin API. Development only, and a no-op in a built book.
|
|
13
|
+
*/
|
|
3
14
|
export function openStory(storyId: string): void
|
package/plugin.js
CHANGED
|
@@ -2,6 +2,11 @@ export function sendEvent(event, payload) {
|
|
|
2
2
|
if (window.__HST_PLUGIN_API__) {
|
|
3
3
|
return window.__HST_PLUGIN_API__.sendEvent(event, payload)
|
|
4
4
|
}
|
|
5
|
+
// The dev server installs that API and a built book has no plugin host, so
|
|
6
|
+
// this is the ordinary path there. Resolve rather than fall off the end: the
|
|
7
|
+
// signature promises a `Promise`, and returning `undefined` meant
|
|
8
|
+
// `sendEvent(...).then(...)` threw in a built book while `await` was fine.
|
|
9
|
+
return Promise.resolve(undefined)
|
|
5
10
|
}
|
|
6
11
|
|
|
7
12
|
export function openStory(storyId) {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const css = ".__pvt-shade {\n height: 80px;\n border-radius: 4px;\n}\n\n.__pvt-text {\n font-size: 4rem;\n display: flex;\n align-items: flex-end;\n}\n\n.__pvt-border {\n border-style: solid;\n border-width: 2px;\n}\n\n.__pvt-spaces {\n background-color: rgb(113 113 122 / 0.1);\n width: min-content;\n}\n\n.__pvt-margin {\n border: dashed 1px rgb(113 113 122 / 0.5);\n width: min-content;\n}\n\n.__pvt-spaces-box,\n.__pvt-margin-box {\n width: 5rem;\n height: 5rem;\n background-color: rgb(113 113 122 / 0.5);\n}\n\n.__pvt-spaces,\n.__pvt-spaces-box,\n.__pvt-margin,\n.__pvt-margin-box,\n.__pvt-drop-shadow {\n border-radius: 4px;\n}\n\n.__pvt-truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.__pvt-drop-shadow {\n width: 8rem;\n height: 8rem;\n background: white;\n margin-bottom: 0.5rem;\n}\n\n.__pvt-drop-shadow {\n background: #4e4e57;\n}\n\n.__pvt-border-radius {\n width: 8rem;\n height: 8rem;\n background-color: rgb(113 113 122 / 0.5);\n}\n\n.__pvt-border-width {\n width: 8rem;\n height: 8rem;\n border-color: rgb(113 113 122 / 0.5);\n background-color: rgb(113 113 122 / 0.1);\n}\n\n.__pvt-width {\n background-color: rgb(113 113 122 / 0.1);\n}\n\n.__pvt-width-box,\n.__pvt-height {\n background-color: rgb(113 113 122 / 0.5);\n}\n\n.__pvt-width-box {\n height: 5rem;\n}";
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
// Injected as `style.css` next to the generated story file, so it styles
|
|
2
|
-
// the Pinceau token stories without reaching the book's own stylesheet.
|
|
3
|
-
export const css = `.__pvt-shade {
|
|
4
|
-
height: 80px;
|
|
5
|
-
border-radius: 4px;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
.__pvt-text {
|
|
9
|
-
font-size: 4rem;
|
|
10
|
-
display: flex;
|
|
11
|
-
align-items: flex-end;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.__pvt-border {
|
|
15
|
-
border-style: solid;
|
|
16
|
-
border-width: 2px;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
.__pvt-spaces {
|
|
20
|
-
background-color: rgb(113 113 122 / 0.1);
|
|
21
|
-
width: min-content;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
.__pvt-margin {
|
|
25
|
-
border: dashed 1px rgb(113 113 122 / 0.5);
|
|
26
|
-
width: min-content;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
.__pvt-spaces-box,
|
|
30
|
-
.__pvt-margin-box {
|
|
31
|
-
width: 5rem;
|
|
32
|
-
height: 5rem;
|
|
33
|
-
background-color: rgb(113 113 122 / 0.5);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
.__pvt-spaces,
|
|
37
|
-
.__pvt-spaces-box,
|
|
38
|
-
.__pvt-margin,
|
|
39
|
-
.__pvt-margin-box,
|
|
40
|
-
.__pvt-drop-shadow {
|
|
41
|
-
border-radius: 4px;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
.__pvt-truncate {
|
|
45
|
-
overflow: hidden;
|
|
46
|
-
text-overflow: ellipsis;
|
|
47
|
-
white-space: nowrap;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.__pvt-drop-shadow {
|
|
51
|
-
width: 8rem;
|
|
52
|
-
height: 8rem;
|
|
53
|
-
background: white;
|
|
54
|
-
margin-bottom: 0.5rem;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.__pvt-drop-shadow {
|
|
58
|
-
background: #4e4e57;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.__pvt-border-radius {
|
|
62
|
-
width: 8rem;
|
|
63
|
-
height: 8rem;
|
|
64
|
-
background-color: rgb(113 113 122 / 0.5);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.__pvt-border-width {
|
|
68
|
-
width: 8rem;
|
|
69
|
-
height: 8rem;
|
|
70
|
-
border-color: rgb(113 113 122 / 0.5);
|
|
71
|
-
background-color: rgb(113 113 122 / 0.1);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.__pvt-width {
|
|
75
|
-
background-color: rgb(113 113 122 / 0.1);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
.__pvt-width-box,
|
|
79
|
-
.__pvt-height {
|
|
80
|
-
background-color: rgb(113 113 122 / 0.5);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
.__pvt-width-box {
|
|
84
|
-
height: 5rem;
|
|
85
|
-
}`;
|
|
@@ -1,424 +0,0 @@
|
|
|
1
|
-
import { join } from 'pathe';
|
|
2
|
-
import { getInjectedImport } from '../util/vendors.js';
|
|
3
|
-
import { css } from './pinceau-tokens-style.js';
|
|
4
|
-
export function pinceauTokens(_options = {}) {
|
|
5
|
-
const themePath = join(process.cwd(), 'node_modules/.vite/pinceau/index.js');
|
|
6
|
-
async function generate(api) {
|
|
7
|
-
try {
|
|
8
|
-
await api.fs.ensureDir(api.pluginTempDir);
|
|
9
|
-
await api.fs.emptyDir(api.pluginTempDir);
|
|
10
|
-
api.moduleLoader.clearCache();
|
|
11
|
-
await api.fs.writeFile(api.path.resolve(api.pluginTempDir, 'style.css'), css);
|
|
12
|
-
const theme = await api.moduleLoader.loadModule(themePath);
|
|
13
|
-
const storyFile = api.path.resolve(api.pluginTempDir, 'Pinceau.story.js');
|
|
14
|
-
await api.fs.writeFile(storyFile, storyTemplate(theme));
|
|
15
|
-
api.addStoryFile(storyFile);
|
|
16
|
-
}
|
|
17
|
-
catch (e) {
|
|
18
|
-
api.error(e.stack ?? e.message);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return {
|
|
22
|
-
name: 'builtin:pinceau-tokens',
|
|
23
|
-
config(config) {
|
|
24
|
-
// Add 'design-system' group
|
|
25
|
-
if (!config.tree) {
|
|
26
|
-
config.tree = {};
|
|
27
|
-
}
|
|
28
|
-
if (!config.tree.groups) {
|
|
29
|
-
config.tree.groups = [];
|
|
30
|
-
}
|
|
31
|
-
if (!config.tree.groups.some(g => g.id === 'design-system')) {
|
|
32
|
-
let index = 0;
|
|
33
|
-
// After 'top' group
|
|
34
|
-
const topIndex = config.tree.groups.findIndex(g => g.id === 'top');
|
|
35
|
-
if (topIndex > -1) {
|
|
36
|
-
index = topIndex + 1;
|
|
37
|
-
}
|
|
38
|
-
// Insert group
|
|
39
|
-
config.tree.groups.splice(index, 0, {
|
|
40
|
-
id: 'design-system',
|
|
41
|
-
title: 'Design System',
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
async onDev(api, onCleanup) {
|
|
46
|
-
await generate(api);
|
|
47
|
-
const watcher = api.watcher.watch(themePath)
|
|
48
|
-
.on('change', () => generate(api))
|
|
49
|
-
.on('add', () => generate(api));
|
|
50
|
-
onCleanup(() => {
|
|
51
|
-
watcher.close();
|
|
52
|
-
});
|
|
53
|
-
},
|
|
54
|
-
async onBuild(api) {
|
|
55
|
-
await generate(api);
|
|
56
|
-
},
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
function storyTemplate(pinceauConfig) {
|
|
60
|
-
pinceauConfig = pinceauConfig?.theme || pinceauConfig?.default?.theme || {};
|
|
61
|
-
// No `import 'poveste-style'` — see the tailwind plugin's template (#219).
|
|
62
|
-
return `import './style.css'
|
|
63
|
-
import { createApp, h, markRaw, ref } from ${getInjectedImport('@poveste/vendors/vue')}
|
|
64
|
-
import {
|
|
65
|
-
HstColorShades,
|
|
66
|
-
HstTokenList,
|
|
67
|
-
HstTokenGrid,
|
|
68
|
-
HstText,
|
|
69
|
-
HstTextarea,
|
|
70
|
-
HstNumber,
|
|
71
|
-
} from ${getInjectedImport('@poveste/controls')}
|
|
72
|
-
|
|
73
|
-
const config = markRaw(${JSON.stringify(pinceauConfig, null, 2)})
|
|
74
|
-
const search = ref('')
|
|
75
|
-
const sampleText = ref('Cat sit like bread eat prawns daintily with a claw then lick paws clean wash down prawns with a lap of carnation milk then retire to the warmest spot on the couch to claw at the fabric before taking a catnap mrow cat cat moo moo lick ears lick paws')
|
|
76
|
-
const fontSize = ref(16)
|
|
77
|
-
const flattenTokens = (data, transformValue = (value) => (value?.value || value)) => {
|
|
78
|
-
const output = {}
|
|
79
|
-
function step(obj, prev) {
|
|
80
|
-
Object.keys(obj).forEach((key) => {
|
|
81
|
-
const value = obj[key]
|
|
82
|
-
const isarray = Array.isArray(value)
|
|
83
|
-
const type = Object.prototype.toString.call(value)
|
|
84
|
-
const isobject
|
|
85
|
-
= type === '[object Object]'
|
|
86
|
-
|| type === '[object Array]'
|
|
87
|
-
|
|
88
|
-
const newKey = prev ? prev + '.' + key : key
|
|
89
|
-
|
|
90
|
-
if (value.value && !output[newKey]) {
|
|
91
|
-
output[newKey] = transformValue(value)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (!isarray && isobject && Object.keys(value).length) { return step(value, newKey) }
|
|
95
|
-
})
|
|
96
|
-
}
|
|
97
|
-
step(data)
|
|
98
|
-
return output
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function mountApp ({ el, state, onUnmount }, render) {
|
|
102
|
-
Object.assign(state, {
|
|
103
|
-
search,
|
|
104
|
-
sampleText,
|
|
105
|
-
fontSize,
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
const app = createApp({
|
|
109
|
-
render,
|
|
110
|
-
})
|
|
111
|
-
app.mount(el)
|
|
112
|
-
|
|
113
|
-
onUnmount(() => {
|
|
114
|
-
app.unmount()
|
|
115
|
-
})
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/*
|
|
119
|
-
media?: PinceauTokens
|
|
120
|
-
colors?: ScaleTokens
|
|
121
|
-
fonts?: PinceauTokens
|
|
122
|
-
fontWeights?: FontWeightTokens
|
|
123
|
-
fontSizes?: BreakpointsTokens
|
|
124
|
-
size?: BreakpointsTokens
|
|
125
|
-
space?: BreakpointsTokens
|
|
126
|
-
radii?: BreakpointsTokens
|
|
127
|
-
borders?: BreakpointsTokens
|
|
128
|
-
borderWidths?: BreakpointsTokens
|
|
129
|
-
borderStyles?: BreakpointsTokens
|
|
130
|
-
shadows?: BreakpointsTokens
|
|
131
|
-
opacity?: BreakpointsTokens
|
|
132
|
-
leads?: BreakpointsTokens
|
|
133
|
-
letterSpacings?: BreakpointsTokens
|
|
134
|
-
transitions?: PinceauTokens
|
|
135
|
-
zIndices?: PinceauTokens
|
|
136
|
-
*/
|
|
137
|
-
|
|
138
|
-
export default {
|
|
139
|
-
id: 'pinceau',
|
|
140
|
-
title: 'Pinceau',
|
|
141
|
-
group: 'design-system',
|
|
142
|
-
icon: 'noto:paintbrush',
|
|
143
|
-
responsiveDisabled: true,
|
|
144
|
-
layout: { type: 'single', iframe: false },
|
|
145
|
-
variants: [
|
|
146
|
-
{
|
|
147
|
-
id: 'media-queries',
|
|
148
|
-
title: 'Media Queries',
|
|
149
|
-
icon: 'carbon:screen',
|
|
150
|
-
onMount: (api) => mountApp(api, () => h(HstTokenGrid, {
|
|
151
|
-
tokens: flattenTokens(config.media),
|
|
152
|
-
getName: key => '@mq.' + key,
|
|
153
|
-
colSize: 180,
|
|
154
|
-
}, ({ token }) => h('div', {
|
|
155
|
-
class: '__pvt-drop-shadow',
|
|
156
|
-
}))),
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
id: 'colors',
|
|
160
|
-
title: 'Colors',
|
|
161
|
-
icon: 'carbon:color-palette',
|
|
162
|
-
onMount: (api) => mountApp(api, () => Object.entries(config.colors).map(([key, shades]) => h(HstColorShades, {
|
|
163
|
-
key,
|
|
164
|
-
shades: shades.value ? { DEFAULT: shades.value } : flattenTokens(shades),
|
|
165
|
-
getName: shade => '{colors.' + key + '.' + shade + '}',
|
|
166
|
-
search: search.value,
|
|
167
|
-
}, ({ color}) => h('div', {
|
|
168
|
-
class: '__pvt-shade',
|
|
169
|
-
style: {
|
|
170
|
-
backgroundColor: color,
|
|
171
|
-
},
|
|
172
|
-
})))),
|
|
173
|
-
onMountControls: (api) => mountApp(api, () => [
|
|
174
|
-
h(HstText, {
|
|
175
|
-
title: 'Filter...',
|
|
176
|
-
modelValue: search.value,
|
|
177
|
-
'onUpdate:modelValue': value => { search.value = value },
|
|
178
|
-
}),
|
|
179
|
-
]),
|
|
180
|
-
},
|
|
181
|
-
// SPACES
|
|
182
|
-
{
|
|
183
|
-
id: 'Spaces',
|
|
184
|
-
title: 'Spaces',
|
|
185
|
-
icon: 'carbon:area',
|
|
186
|
-
onMount: (api) => mountApp(api, () => h(HstTokenList, {
|
|
187
|
-
tokens: flattenTokens(config.space),
|
|
188
|
-
getName: key => '{space.' + key + '}',
|
|
189
|
-
}, ({ token }) => h('div', {
|
|
190
|
-
class: '__pvt-spaces',
|
|
191
|
-
style: {
|
|
192
|
-
padding: token.value,
|
|
193
|
-
},
|
|
194
|
-
}, [
|
|
195
|
-
h('div', {
|
|
196
|
-
class: '__pvt-spaces-box',
|
|
197
|
-
}),
|
|
198
|
-
]))),
|
|
199
|
-
},
|
|
200
|
-
// SIZES
|
|
201
|
-
{
|
|
202
|
-
id: 'sizes',
|
|
203
|
-
title: 'Sizes',
|
|
204
|
-
icon: 'carbon:pan-horizontal',
|
|
205
|
-
onMount: (api) => mountApp(api, () => h(HstTokenList, {
|
|
206
|
-
tokens: flattenTokens(config.size),
|
|
207
|
-
getName: key => '{size.' + key + '}',
|
|
208
|
-
}, ({ token }) => h('div', {
|
|
209
|
-
class: '__pvt-width',
|
|
210
|
-
}, [
|
|
211
|
-
h('div', {
|
|
212
|
-
class: '__pvt-width-box',
|
|
213
|
-
style: {
|
|
214
|
-
width: token.value,
|
|
215
|
-
},
|
|
216
|
-
}),
|
|
217
|
-
]))),
|
|
218
|
-
},
|
|
219
|
-
// FONTSIZES
|
|
220
|
-
{
|
|
221
|
-
id: 'font-size',
|
|
222
|
-
title: 'Font Size',
|
|
223
|
-
icon: 'carbon:text-font',
|
|
224
|
-
onMount: (api) => mountApp(api, () => h(HstTokenList, {
|
|
225
|
-
tokens: flattenTokens(config.fontSizes),
|
|
226
|
-
getName: key => '{fontSizes.' + key + '}',
|
|
227
|
-
}, ({ token }) => h('div', {
|
|
228
|
-
class: '__pvt-truncate',
|
|
229
|
-
style: {
|
|
230
|
-
fontSize: token.value,
|
|
231
|
-
},
|
|
232
|
-
}, sampleText.value))),
|
|
233
|
-
onMountControls: (api) => mountApp(api, () => [
|
|
234
|
-
h(HstTextarea, {
|
|
235
|
-
title: 'Sample text',
|
|
236
|
-
modelValue: sampleText.value,
|
|
237
|
-
'onUpdate:modelValue': value => { sampleText.value = value },
|
|
238
|
-
rows: 5,
|
|
239
|
-
}),
|
|
240
|
-
]),
|
|
241
|
-
},
|
|
242
|
-
// FONTWEIGHTS
|
|
243
|
-
{
|
|
244
|
-
id: 'font-weight',
|
|
245
|
-
title: 'Font Weight',
|
|
246
|
-
icon: 'carbon:text-font',
|
|
247
|
-
onMount: (api) => mountApp(api, () => h(HstTokenList, {
|
|
248
|
-
tokens: flattenTokens(config.fontWeights),
|
|
249
|
-
getName: key => '{fontWeights.' + key + '}',
|
|
250
|
-
}, ({ token }) => h('div', {
|
|
251
|
-
class: '__pvt-truncate',
|
|
252
|
-
style: {
|
|
253
|
-
fontWeight: token.value,
|
|
254
|
-
fontSize: \`\${fontSize.value}px\`,
|
|
255
|
-
},
|
|
256
|
-
}, sampleText.value))),
|
|
257
|
-
onMountControls: (api) => mountApp(api, () => [
|
|
258
|
-
h(HstTextarea, {
|
|
259
|
-
title: 'Sample text',
|
|
260
|
-
modelValue: sampleText.value,
|
|
261
|
-
'onUpdate:modelValue': value => { sampleText.value = value },
|
|
262
|
-
rows: 5,
|
|
263
|
-
}),
|
|
264
|
-
h(HstNumber, {
|
|
265
|
-
title: 'Font size',
|
|
266
|
-
modelValue: fontSize.value,
|
|
267
|
-
'onUpdate:modelValue': value => { fontSize.value = value },
|
|
268
|
-
min: 1,
|
|
269
|
-
}),
|
|
270
|
-
]),
|
|
271
|
-
},
|
|
272
|
-
// FONTS
|
|
273
|
-
{
|
|
274
|
-
id: 'fonts',
|
|
275
|
-
title: 'Fonts',
|
|
276
|
-
icon: 'carbon:text-font',
|
|
277
|
-
onMount: (api) => mountApp(api, () => h(HstTokenList, {
|
|
278
|
-
tokens: flattenTokens(config.fonts),
|
|
279
|
-
getName: key => '{fonts.' + key + '}',
|
|
280
|
-
}, ({ token }) => h('div', {
|
|
281
|
-
class: '__pvt-truncate',
|
|
282
|
-
style: {
|
|
283
|
-
fontFamily: token.value,
|
|
284
|
-
fontSize: \`\${fontSize.value}px\`,
|
|
285
|
-
},
|
|
286
|
-
}, sampleText.value))),
|
|
287
|
-
onMountControls: (api) => mountApp(api, () => [
|
|
288
|
-
h(HstTextarea, {
|
|
289
|
-
title: 'Sample text',
|
|
290
|
-
modelValue: sampleText.value,
|
|
291
|
-
'onUpdate:modelValue': value => { sampleText.value = value },
|
|
292
|
-
rows: 5,
|
|
293
|
-
}),
|
|
294
|
-
h(HstNumber, {
|
|
295
|
-
title: 'Font size',
|
|
296
|
-
modelValue: fontSize.value,
|
|
297
|
-
'onUpdate:modelValue': value => { fontSize.value = value },
|
|
298
|
-
min: 1,
|
|
299
|
-
}),
|
|
300
|
-
]),
|
|
301
|
-
},
|
|
302
|
-
// LETTERSPACINGS
|
|
303
|
-
{
|
|
304
|
-
id: 'letter-spacing',
|
|
305
|
-
title: 'Letter Spacing',
|
|
306
|
-
icon: 'carbon:text-font',
|
|
307
|
-
onMount: (api) => mountApp(api, () => h(HstTokenList, {
|
|
308
|
-
tokens: flattenTokens(config.letterSpacings),
|
|
309
|
-
getName: key => '{letterSpacings.' + key + '}',
|
|
310
|
-
}, ({ token }) => h('div', {
|
|
311
|
-
class: '__pvt-truncate',
|
|
312
|
-
style: {
|
|
313
|
-
letterSpacing: token.value,
|
|
314
|
-
fontSize: \`\${fontSize.value}px\`,
|
|
315
|
-
},
|
|
316
|
-
}, sampleText.value))),
|
|
317
|
-
onMountControls: (api) => mountApp(api, () => [
|
|
318
|
-
h(HstTextarea, {
|
|
319
|
-
title: 'Sample text',
|
|
320
|
-
modelValue: sampleText.value,
|
|
321
|
-
'onUpdate:modelValue': value => { sampleText.value = value },
|
|
322
|
-
rows: 5,
|
|
323
|
-
}),
|
|
324
|
-
h(HstNumber, {
|
|
325
|
-
title: 'Font size',
|
|
326
|
-
modelValue: fontSize.value,
|
|
327
|
-
'onUpdate:modelValue': value => { fontSize.value = value },
|
|
328
|
-
min: 1,
|
|
329
|
-
}),
|
|
330
|
-
]),
|
|
331
|
-
},
|
|
332
|
-
// LEADS
|
|
333
|
-
{
|
|
334
|
-
id: 'leads',
|
|
335
|
-
title: 'Leads',
|
|
336
|
-
icon: 'carbon:text-font',
|
|
337
|
-
onMount: (api) => mountApp(api, () => h(HstTokenList, {
|
|
338
|
-
tokens: flattenTokens(config.leads),
|
|
339
|
-
getName: key => '{leads.' + key + '}',
|
|
340
|
-
}, ({ token }) => h('div', {
|
|
341
|
-
style: {
|
|
342
|
-
lineHeight: token.value,
|
|
343
|
-
},
|
|
344
|
-
}, sampleText.value))),
|
|
345
|
-
onMountControls: (api) => mountApp(api, () => [
|
|
346
|
-
h(HstTextarea, {
|
|
347
|
-
title: 'Sample text',
|
|
348
|
-
modelValue: sampleText.value,
|
|
349
|
-
'onUpdate:modelValue': value => { sampleText.value = value },
|
|
350
|
-
rows: 5,
|
|
351
|
-
}),
|
|
352
|
-
// @TODO select font size
|
|
353
|
-
]),
|
|
354
|
-
},
|
|
355
|
-
// SHADOWS
|
|
356
|
-
{
|
|
357
|
-
id: 'shadows',
|
|
358
|
-
title: 'Shadows',
|
|
359
|
-
icon: 'carbon:shape-except',
|
|
360
|
-
onMount: (api) => mountApp(api, () => h(HstTokenGrid, {
|
|
361
|
-
tokens: flattenTokens(config.shadows),
|
|
362
|
-
getName: key => '{shadows.' + key + '}',
|
|
363
|
-
colSize: 180,
|
|
364
|
-
}, ({ token }) => h('div', {
|
|
365
|
-
class: '__pvt-drop-shadow',
|
|
366
|
-
style: 'box-shadow:' + token.value,
|
|
367
|
-
}))),
|
|
368
|
-
},
|
|
369
|
-
// OPACITIES
|
|
370
|
-
{
|
|
371
|
-
id: 'opacities',
|
|
372
|
-
title: 'Opacities',
|
|
373
|
-
icon: 'carbon:bring-forward',
|
|
374
|
-
onMount: (api) => mountApp(api, () => h(HstTokenGrid, {
|
|
375
|
-
tokens: flattenTokens(config.opacity),
|
|
376
|
-
getName: key => '{opacity.' + key + '}',
|
|
377
|
-
colSize: 180,
|
|
378
|
-
}, ({ token }) => h('div', {
|
|
379
|
-
class: '__pvt-drop-shadow',
|
|
380
|
-
style: 'opacity:' + token.value,
|
|
381
|
-
}))),
|
|
382
|
-
},
|
|
383
|
-
// RADII
|
|
384
|
-
{
|
|
385
|
-
id: 'border-radius',
|
|
386
|
-
title: 'Border Radius',
|
|
387
|
-
icon: 'carbon:condition-wait-point',
|
|
388
|
-
onMount: (api) => mountApp(api, () => h(HstTokenGrid, {
|
|
389
|
-
tokens: flattenTokens(config.radii),
|
|
390
|
-
getName: key => '{radii.' + key + '}',
|
|
391
|
-
colSize: 180,
|
|
392
|
-
}, ({ token }) => h('div', {
|
|
393
|
-
class: '__pvt-border-radius',
|
|
394
|
-
style: {
|
|
395
|
-
borderRadius: token.value,
|
|
396
|
-
},
|
|
397
|
-
}))),
|
|
398
|
-
},
|
|
399
|
-
// BORDERWIDTHS
|
|
400
|
-
{
|
|
401
|
-
id: 'border-width',
|
|
402
|
-
title: 'Border Width',
|
|
403
|
-
icon: 'carbon:checkbox',
|
|
404
|
-
onMount: (api) => mountApp(api, () => h(HstTokenGrid, {
|
|
405
|
-
tokens: flattenTokens(config.borderWidths),
|
|
406
|
-
getName: key => '{borderWidths.' + key + '}',
|
|
407
|
-
colSize: 180,
|
|
408
|
-
}, ({ token }) => h('div', {
|
|
409
|
-
class: '__pvt-border-width',
|
|
410
|
-
style: {
|
|
411
|
-
borderWidth: token.value,
|
|
412
|
-
},
|
|
413
|
-
}))),
|
|
414
|
-
},
|
|
415
|
-
// FULL CONFIG
|
|
416
|
-
{
|
|
417
|
-
id: 'full-config',
|
|
418
|
-
title: 'Full Config',
|
|
419
|
-
icon: 'carbon:code',
|
|
420
|
-
onMount: (api) => mountApp(api, () => h('pre', JSON.stringify(config, null, 2))),
|
|
421
|
-
},
|
|
422
|
-
],
|
|
423
|
-
}`;
|
|
424
|
-
}
|