Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | 117x 117x 117x 117x 117x 117x | import { DateTime } from 'luxon';
import { Plugin } from '../model/plugin';
import { Mod } from '../model/tag';
import { imagePlugin } from './media/image';
import { videoPlugin } from './media/video';
export const thumbnailPlugin: Plugin = {
tag: 'plugin/thumbnail',
name: $localize`⭕️ Thumbnail`,
config: {
mod: $localize`⭕️ Thumbnail`,
version: 1,
type: 'plugin',
default: true,
proxy: true,
add: true,
generated: $localize`Generated by jasper-ui ${DateTime.now().toISO()}`,
description: $localize`Activates built-in thumbnail support and allows users to add thumbnails to Refs.`,
aiInstructions: `# plugin/thumbnail
The thumbnail plugin is installed, which means a thumbnail may/may not be displayed to the left of the title.
The thumbnail is enabled with the plugin/thumbnail plugin and can be set by either the Ref url or the plugin
data url. However, if a Ref does not have a thumbnail set, it may inherit a default thumbnail from a Plugin.
For example, the plugin/thread Plugin has the following icons set:
\`\`\`json
icons: [{ thumbnail: $localize\`🧵️\` }],
\`\`\`
While the plugin/chat Plugins has this:
\`\`\`json
icons: [{ thumbnail: $localize\`💬️\`, order: 1 }],
\`\`\`
So if they were on the same Ref, the plugin/chat would take priority and that
would be the thumbnail.
`,
filters: [
{ query: 'plugin/thumbnail', label: $localize`⭕️ thumbnail`, title: $localize`Has Thumbnail`, group: $localize`Plugins 🧰️` },
],
extensions: [...videoPlugin.config!.extensions!, ...imagePlugin.config!.extensions!],
bulkForm: true,
advancedForm: [{
key: 'url',
type: 'image',
props: {
label: $localize`URL:`,
},
}, {
key: 'color',
type: 'color',
props: {
label: $localize`Color:`,
},
}, {
key: 'emoji',
type: 'string',
props: {
label: $localize`Emoji:`,
},
}, {
key: 'radius',
type: 'range',
defaultValue: 0,
props: {
label: $localize`Radius:`,
min: 0,
max: 24,
step: 4,
},
}],
},
schema: {
optionalProperties: {
url: { type: 'string' },
color: { type: 'string' },
emoji: { type: 'string' },
radius: { type: 'int32' },
},
},
};
export const storyboardPlugin: Plugin = {
tag: 'plugin/thumbnail/storyboard',
name: $localize`📽️ Storyboard`,
config: {
mod: $localize`⭕️ Thumbnail`,
version: 1,
type: 'plugin',
default: true,
generated: $localize`Generated by jasper-ui ${DateTime.now().toISO()}`,
description: $localize`Storyboard thumbnail data for hover-triggered slideshows.`,
// language=CSS
css: `
.ref.plugin_thumbnail_storyboard.has-storyboard-default .thumbnail,
.ref.plugin_thumbnail_storyboard.storyboard-ready:hover .thumbnail {
width: var(--storyboard-width) !important;
height: var(--storyboard-height) !important;
margin: var(--storyboard-margin) !important;
background-image: var(--storyboard-url) !important;
background-size: var(--storyboard-size) !important;
background-position: 0% 0%;
}
.ref.plugin_thumbnail_storyboard.storyboard-ready:hover .thumbnail {
animation: var(--storyboard-animation) !important;
}
`,
},
schema: {
optionalProperties: {
url: { type: 'string' },
width: { type: 'int32' },
height: { type: 'int32' },
rows: { type: 'int32' },
cols: { type: 'int32' },
},
},
};
export const thumbnailMod: Mod = {
plugin: [
thumbnailPlugin,
storyboardPlugin,
]
};
export function generateStoryboardKeyframes(name: string, cols: number, rows: number): string {
if (cols <= 0 || rows <= 0) return '';
const totalFrames = cols * rows;
const lines: string[] = [`@keyframes ${name} {`];
for (let i = 0; i < totalFrames; i++) {
const col = i % cols;
const row = Math.floor(i / cols);
const pct = ((i / totalFrames) * 100).toFixed(4);
const x = cols === 1 ? '0%' : `${(col / (cols - 1)) * 100}%`;
const y = rows === 1 ? '0%' : `${(row / (rows - 1)) * 100}%`;
lines.push(` ${pct}% { background-position: ${x} ${y}; animation-timing-function: step-end; }`);
}
lines.push('}');
return lines.join('\n');
}
|