mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-08-06 04:37:37 +00:00
Merge pull request #4769 from Gazook89/Better-Dropdowns
Better dropdowns
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import Admin from './admin.jsx';
|
||||
import { bootstrapAnchorPositioningPolyfill } from '../components/anchorPositioningPolyfill.js';
|
||||
|
||||
const props = window.__INITIAL_PROPS__ || {};
|
||||
|
||||
createRoot(document.getElementById('reactRoot')).render(<Admin {...props} />);
|
||||
bootstrapAnchorPositioningPolyfill();
|
||||
|
||||
@@ -71,10 +71,14 @@ const Anchored = ({ children })=>{
|
||||
// forward ref for AnchoredTrigger
|
||||
const AnchoredTrigger = forwardRef(({ toggleVisibility, visible, children, className, ...props }, ref)=>(
|
||||
<button
|
||||
ref={ref}
|
||||
ref={(el)=>{
|
||||
// setAttribute bypasses React's style sanitization so the anchor polyfill can read it
|
||||
el?.setAttribute('style', `anchor-name: --${props.id}`);
|
||||
if(typeof ref === 'function') ref(el);
|
||||
else if(ref) ref.current = el;
|
||||
}}
|
||||
className={`anchored-trigger${visible ? ' active' : ''} ${className}`}
|
||||
onClick={toggleVisibility}
|
||||
style={{ anchorName: `--${props.id}` }} // setting anchor properties here allows greater recyclability.
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
@@ -84,9 +88,12 @@ const AnchoredTrigger = forwardRef(({ toggleVisibility, visible, children, class
|
||||
// forward ref for AnchoredBox
|
||||
const AnchoredBox = forwardRef(({ visible, children, className, anchorId, ...props }, ref)=>(
|
||||
<div
|
||||
ref={ref}
|
||||
ref={(el)=>{
|
||||
el?.setAttribute('style', `position-anchor: --${anchorId}`);
|
||||
if(typeof ref === 'function') ref(el);
|
||||
else if(ref) ref.current = el;
|
||||
}}
|
||||
className={`anchored-box${visible ? ' active' : ''} ${className}`}
|
||||
style={{ positionAnchor: `--${anchorId}` }} // setting anchor properties here allows greater recyclability.
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
|
||||
|
||||
.anchored-box {
|
||||
position : absolute;
|
||||
visibility : hidden;
|
||||
justify-self : anchor-center;
|
||||
@supports (inset-block-start: anchor(bottom)) {
|
||||
inset-block-start : anchor(bottom);
|
||||
}
|
||||
position : absolute;
|
||||
visibility : hidden;
|
||||
justify-self : anchor-center;
|
||||
inset-block-start : anchor(bottom);
|
||||
&.active { visibility : visible; }
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
This file basically checks support for Anchor Positioning API in the browser,
|
||||
and then loads the Oddbird polyfill if support is lacking.
|
||||
*/
|
||||
|
||||
let polyfillPromise;
|
||||
|
||||
// look for `anchorName` in the computed styles
|
||||
const supportsAnchorPositioning = ()=>'anchorName' in document.documentElement.style;
|
||||
|
||||
export const bootstrapAnchorPositioningPolyfill = ()=>{
|
||||
if(supportsAnchorPositioning()) return Promise.resolve(false);
|
||||
if(polyfillPromise) return polyfillPromise;
|
||||
|
||||
polyfillPromise = (async ()=>{
|
||||
try {
|
||||
const { default: polyfill } = await import('@oddbird/css-anchor-positioning/fn');
|
||||
await polyfill();
|
||||
return true;
|
||||
} catch (error){
|
||||
polyfillPromise = undefined;
|
||||
throw error;
|
||||
}
|
||||
})();
|
||||
|
||||
return polyfillPromise;
|
||||
};
|
||||
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* A dropdown menu component that uses the Anchor Positioning API to position the elements. It supports nested submenus as well.
|
||||
* Anchor Positioning is now supported in all major browsers. A polyfill is conditionally loaded for older browsers.
|
||||
*
|
||||
* As-is, the menus will always open down aligned on left to trigger, submenus open to the right initially.
|
||||
* If no space, menus will still open down, but aligned to the right of the trigger. Submenus will flip to the other side of the top menu.
|
||||
* This could be customized either in more specific CSS, or as a `direction` prop on the component (in future iterations).
|
||||
*
|
||||
* @param {string} props.groupName - Name of the menu. Appears as the trigger text.
|
||||
* @param {string} [props.icon] - Icon to display in the trigger.
|
||||
* @param {string} [props.color] - Color class to add to the trigger.
|
||||
* @param {string} [props.className] - Additional classes for the menu wrapper.
|
||||
* @param {React.ReactNode} [props.customTrigger] - Custom element to use as a trigger.
|
||||
* @param {React.ReactNode} [props.children] - Child elements to render in the menu.
|
||||
* @returns {React.JSX.Element}
|
||||
*/
|
||||
|
||||
import './dropdown.less';
|
||||
import React, { useEffect, useId, useRef } from 'react';
|
||||
import _ from 'lodash';
|
||||
|
||||
// use react context to keep track of the menu depth (menus in menus)
|
||||
const MenuDepthContext = React.createContext(0);
|
||||
|
||||
const Dropdown = ({ groupName, className = null, icon, children, color = null, customTrigger, ...props })=>{
|
||||
const reactId = useId();
|
||||
const safeId = reactId.replace(/[^a-zA-Z0-9_-]/g, '');
|
||||
const menuId = `${_.kebabCase(groupName)}-${safeId}-menu`;
|
||||
const anchorName = `--${menuId}`;
|
||||
const depth = React.useContext(MenuDepthContext);
|
||||
|
||||
// A menu is a submenu if depth > 0
|
||||
const isSubMenu = depth > 0;
|
||||
|
||||
const triggerRef = useRef(null);
|
||||
const menuRef = useRef(null);
|
||||
|
||||
// use setAttribute instead of the React style prop because React strips unknown CSS
|
||||
// properties (like anchor-name) from inline styles in browsers that don't support them.
|
||||
// setAttribute writes raw CSS text that the anchor positioning polyfill can read
|
||||
useEffect(()=>{
|
||||
triggerRef.current?.setAttribute('style', `anchor-name: ${anchorName}`);
|
||||
menuRef.current?.setAttribute('style', `position-anchor: ${anchorName}`);
|
||||
}, [anchorName]);
|
||||
|
||||
// hide popover with click inside iframe (not supported by light dismiss)
|
||||
useEffect(()=>{
|
||||
const menuElement = document.getElementById(menuId);
|
||||
if(!menuElement) return;
|
||||
|
||||
const handleClick = ()=>{
|
||||
if(menuElement.matches(':popover-open')) {
|
||||
menuElement.hidePopover();
|
||||
}
|
||||
};
|
||||
// Listen for clicks from both the main document and the iframe
|
||||
document.addEventListener('iframe-click', handleClick);
|
||||
return ()=>{
|
||||
document.removeEventListener('iframe-click', handleClick);
|
||||
};
|
||||
}, [menuId]);
|
||||
|
||||
// the trigger is the piece placed inside the opening button of the menu.
|
||||
// This method allows for creating a generic span with the group name,
|
||||
// or using a bespoke element (like a graphic) passed in from props to be used as the trigger
|
||||
const trigger = (groupName = 'menu', icon = '')=>{
|
||||
if(!customTrigger){
|
||||
return <>
|
||||
<i className={icon}></i><span className='menu-name'>{groupName}</span><i className={`caret fas fa-caret-${isSubMenu ? 'right' : 'down'}`}></i>
|
||||
</>;
|
||||
} else {
|
||||
return customTrigger;
|
||||
}
|
||||
};
|
||||
|
||||
// handle clicks on menu items. By default, actions do dismiss.
|
||||
const handleMenuActionClick = (event)=>{
|
||||
const menuElement = menuRef.current;
|
||||
if(!menuElement) return;
|
||||
|
||||
const menuAction = event.target.closest('button, a, [role="menuitem"]');
|
||||
if(!menuAction || !menuElement.contains(menuAction)) return;
|
||||
|
||||
// don't dismiss if the target triggers a submenu
|
||||
if(menuAction.hasAttribute('popovertarget')) return;
|
||||
|
||||
// don't dismiss if the target has `no-dismiss` attribute
|
||||
const noDismissValue = menuAction.getAttribute('no-dismiss')?.toLowerCase();
|
||||
if(noDismissValue === '' || noDismissValue === 'true') return;
|
||||
|
||||
document.querySelectorAll('.menu-list:popover-open').forEach((openMenu)=>openMenu.hidePopover());
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={['menu-wrapper', className].join(' ')} role='none' >
|
||||
<button
|
||||
id={`${menuId}-trigger`}
|
||||
className={['menu-item', color].join(' ')}
|
||||
popoverTarget={menuId}
|
||||
aria-haspopup='menu'
|
||||
role='menuitem'
|
||||
disabled={!React.Children.count(children)}
|
||||
ref={triggerRef}
|
||||
>
|
||||
{trigger(groupName, icon)}
|
||||
</button>
|
||||
<MenuDepthContext.Provider value={depth + 1}>
|
||||
<div
|
||||
ref={menuRef}
|
||||
id={menuId}
|
||||
className='menu-list'
|
||||
popover='auto'
|
||||
role='menu'
|
||||
onClick={handleMenuActionClick}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</MenuDepthContext.Provider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export { Dropdown };
|
||||
@@ -0,0 +1,24 @@
|
||||
.menu-wrapper {
|
||||
position: relative;
|
||||
&:is(.menu-bar > .menu-section > .menu-wrapper){
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-list {
|
||||
position : fixed;
|
||||
z-index : 1000;
|
||||
top : anchor(bottom);
|
||||
left : anchor(left);
|
||||
position-try: flip-inline flip-block;
|
||||
color: inherit; // [popover] gets a `canvastext` color value from useragent.
|
||||
> .menu-wrapper {
|
||||
position:relative;
|
||||
> .menu-list {
|
||||
margin: 0 0px;
|
||||
top : anchor(top);
|
||||
left : anchor(right);
|
||||
position-try: flip-inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
import './snippetbar.less';
|
||||
import React from 'react';
|
||||
import createReactClass from 'create-react-class';
|
||||
import { Dropdown } from '../../../components/dropdown/dropdown.jsx';
|
||||
|
||||
import _ from 'lodash';
|
||||
import cx from 'classnames';
|
||||
@@ -320,36 +321,33 @@ const SnippetGroup = createReactClass({
|
||||
};
|
||||
},
|
||||
handleSnippetClick : function(e, snippet){
|
||||
e.stopPropagation();
|
||||
this.props.onSnippetClick(execute(snippet.gen, this.props));
|
||||
},
|
||||
renderSnippets : function(snippets){
|
||||
return _.map(snippets, (snippet)=>{
|
||||
return <div className='snippet' key={snippet.name} onClick={(e)=>this.handleSnippetClick(e, snippet)}>
|
||||
<i className={snippet.icon} />
|
||||
<span className={`name${snippet.disabled ? ' disabled' : ''}`} title={snippet.name}>{snippet.name}</span>
|
||||
{snippet.experimental && <span className='beta'>beta</span>}
|
||||
{snippet.disabled && <span className='beta' title='temporarily disabled due to large slowdown; under re-design'>disabled</span>}
|
||||
{snippet.subsnippets && <>
|
||||
<i className='fas fa-caret-right'></i>
|
||||
<div className='dropdown side'>
|
||||
if(!snippet.subsnippets){
|
||||
return (
|
||||
<button className='menu-item' key={snippet.name} onClick={(e)=>this.handleSnippetClick(e, snippet)} role='menuitem'>
|
||||
<i className={snippet.icon} />
|
||||
<span className={`name${snippet.disabled ? ' disabled' : ''}`} title={snippet.name}>{snippet.name}</span>
|
||||
{snippet.experimental && <span className='beta'>beta</span>}
|
||||
{snippet.disabled && <span className='beta' title='temporarily disabled due to large slowdown; under re-design'>disabled</span>}
|
||||
</button>
|
||||
);
|
||||
} else if(snippet.subsnippets){
|
||||
return (
|
||||
<Dropdown groupName={snippet.name} icon={snippet.icon} key={snippet.name}>
|
||||
{this.renderSnippets(snippet.subsnippets)}
|
||||
</div></>}
|
||||
</div>;
|
||||
</Dropdown>
|
||||
)
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
|
||||
render : function(){
|
||||
const snippetGroup = `snippetGroup snippetBarButton ${this.props.snippets.length === 0 ? 'disabledSnippets' : ''}`;
|
||||
return <div className={snippetGroup}>
|
||||
<div className='text'>
|
||||
<i className={this.props.icon} />
|
||||
<span className='groupName'>{this.props.groupName}</span>
|
||||
</div>
|
||||
<div className='dropdown'>
|
||||
{this.renderSnippets(this.props.snippets)}
|
||||
</div>
|
||||
</div>;
|
||||
return <Dropdown groupName={this.props.groupName} id={this.props.groupName} icon={this.props.icon}>
|
||||
{this.renderSnippets(this.props.snippets)}
|
||||
</Dropdown>;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
height : auto;
|
||||
color : black;
|
||||
background-color : #DDDDDD;
|
||||
font-size : .65rem;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
text-transform: uppercase;
|
||||
font-weight: 800;
|
||||
|
||||
.snippets {
|
||||
display : flex;
|
||||
@@ -22,7 +26,7 @@
|
||||
display : flex;
|
||||
justify-content : flex-end;
|
||||
min-width : 250px; //must be controlled every time an item is added, must be hardcoded for the wrapping as it is applied
|
||||
|
||||
font-size: .85rem;
|
||||
&:only-child {min-width : unset; margin-left : auto;}
|
||||
|
||||
>div {
|
||||
@@ -57,32 +61,27 @@
|
||||
}
|
||||
&.undo {
|
||||
.tooltipLeft('Undo');
|
||||
font-size : 0.75em;
|
||||
color : grey;
|
||||
&.active { color : inherit; }
|
||||
}
|
||||
&.redo {
|
||||
.tooltipLeft('Redo');
|
||||
font-size : 0.75em;
|
||||
color : grey;
|
||||
&.active { color : inherit; }
|
||||
}
|
||||
&.foldAll {
|
||||
.tooltipLeft('Fold All');
|
||||
font-size : 0.75em;
|
||||
color : grey;
|
||||
&.active { color : inherit; }
|
||||
}
|
||||
&.unfoldAll {
|
||||
.tooltipLeft('Unfold All');
|
||||
font-size : 0.75em;
|
||||
color : grey;
|
||||
&.active { color : inherit; }
|
||||
}
|
||||
&.history {
|
||||
.tooltipLeft('History');
|
||||
position : relative;
|
||||
font-size : 0.75em;
|
||||
color : grey;
|
||||
border : none;
|
||||
&.active { color : inherit; }
|
||||
@@ -93,7 +92,6 @@
|
||||
}
|
||||
&.editorTheme {
|
||||
.tooltipLeft('Editor Themes');
|
||||
font-size : 0.75em;
|
||||
color : inherit;
|
||||
&.active {
|
||||
position : relative;
|
||||
@@ -144,91 +142,97 @@
|
||||
border-left : 1px solid black;
|
||||
.tooltipLeft('Edit Brew Properties');
|
||||
}
|
||||
.snippetGroup {
|
||||
|
||||
&:hover {
|
||||
& > .dropdown { visibility : visible; }
|
||||
}
|
||||
.dropdown {
|
||||
position : absolute;
|
||||
top : 100%;
|
||||
z-index : 1000;
|
||||
visibility : hidden;
|
||||
padding : 0px;
|
||||
margin-left : -5px;
|
||||
background-color : #DDDDDD;
|
||||
.snippet {
|
||||
position : relative;
|
||||
display : flex;
|
||||
align-items : center;
|
||||
min-width : max-content;
|
||||
padding : 5px;
|
||||
font-size : 10px;
|
||||
cursor : pointer;
|
||||
.animate(background-color);
|
||||
i {
|
||||
min-width : 25px;
|
||||
height : 1.2em;
|
||||
margin-right : 8px;
|
||||
font-size : 1.2em;
|
||||
text-align : center;
|
||||
& ~ i {
|
||||
margin-right : 0;
|
||||
margin-left : 5px;
|
||||
}
|
||||
/* Fonts */
|
||||
&.font {
|
||||
height : auto;
|
||||
&::before {
|
||||
font-size : 1em;
|
||||
content : 'ABC';
|
||||
}
|
||||
|
||||
&.OpenSans {font-family : 'OpenSans';}
|
||||
&.CodeBold {font-family : 'CodeBold';}
|
||||
&.CodeLight {font-family : 'CodeLight';}
|
||||
&.ScalySansRemake {font-family : 'ScalySansRemake';}
|
||||
&.BookInsanityRemake {font-family : 'BookInsanityRemake';}
|
||||
&.MrEavesRemake {font-family : 'MrEavesRemake';}
|
||||
&.SolberaImitationRemake {font-family : 'SolberaImitationRemake';}
|
||||
&.ScalySansSmallCapsRemake {font-family : 'ScalySansSmallCapsRemake';}
|
||||
&.WalterTurncoat {font-family : 'WalterTurncoat';}
|
||||
&.Lato {font-family : 'Lato';}
|
||||
&.Courier {font-family : 'Courier';}
|
||||
&.NodestoCapsCondensed {font-family : 'NodestoCapsCondensed';}
|
||||
&.Overpass {font-family : 'Overpass';}
|
||||
&.Davek {font-family : 'Davek';}
|
||||
&.Iokharic {font-family : 'Iokharic';}
|
||||
&.Rellanic {font-family : 'Rellanic';}
|
||||
&.TimesNewRoman {font-family : 'Times New Roman';}
|
||||
}
|
||||
}
|
||||
.name { margin-right : auto; }
|
||||
.disabled { text-decoration : line-through; }
|
||||
.beta {
|
||||
align-self : center;
|
||||
padding : 4px 6px;
|
||||
margin-left : 5px;
|
||||
font-family : monospace;
|
||||
line-height : 1em;
|
||||
color : white;
|
||||
background : grey;
|
||||
border-radius : 12px;
|
||||
}
|
||||
&:hover {
|
||||
background-color : #999999;
|
||||
& > .dropdown {
|
||||
visibility : visible;
|
||||
&.side {
|
||||
top : 0%;
|
||||
left : 100%;
|
||||
margin-left : 0;
|
||||
box-shadow : -1px 1px 2px 0px #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-wrapper {
|
||||
.menu-item:is(.snippets > .menu-wrapper > .menu-item):first-child {
|
||||
.caret {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.menu-list {
|
||||
padding : 0px;
|
||||
background-color : #DDDDDD;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
position : relative;
|
||||
display : flex;
|
||||
justify-content: space-between;
|
||||
align-items : center;
|
||||
min-width : max-content;
|
||||
padding : 5px;
|
||||
cursor : pointer;
|
||||
width: 100%;
|
||||
.animate(background-color);
|
||||
&:is(.menu-list .menu-item) [class*="name"] {
|
||||
padding-inline: 8px;
|
||||
}
|
||||
.menu-name {
|
||||
flex: 1;
|
||||
text-align: left;
|
||||
text-box-trim: trim-end;
|
||||
}
|
||||
i {
|
||||
min-width : 25px;
|
||||
height : .85rem;
|
||||
font-size : 1.2em;
|
||||
text-align : center;
|
||||
&.caret {
|
||||
margin-right: 0;
|
||||
}
|
||||
&.caret:is(.menu-wrapper .menu-wrapper * ) {
|
||||
text-align: right;
|
||||
}
|
||||
/* Fonts */
|
||||
&.font {
|
||||
height : auto;
|
||||
&::before {
|
||||
font-size : 1em;
|
||||
content : 'ABC';
|
||||
}
|
||||
|
||||
&.OpenSans {font-family : 'OpenSans';}
|
||||
&.CodeBold {font-family : 'CodeBold';}
|
||||
&.CodeLight {font-family : 'CodeLight';}
|
||||
&.ScalySansRemake {font-family : 'ScalySansRemake';}
|
||||
&.BookInsanityRemake {font-family : 'BookInsanityRemake';}
|
||||
&.MrEavesRemake {font-family : 'MrEavesRemake';}
|
||||
&.SolberaImitationRemake {font-family : 'SolberaImitationRemake';}
|
||||
&.ScalySansSmallCapsRemake {font-family : 'ScalySansSmallCapsRemake';}
|
||||
&.WalterTurncoat {font-family : 'WalterTurncoat';}
|
||||
&.Lato {font-family : 'Lato';}
|
||||
&.Courier {font-family : 'Courier';}
|
||||
&.NodestoCapsCondensed {font-family : 'NodestoCapsCondensed';}
|
||||
&.Overpass {font-family : 'Overpass';}
|
||||
&.Davek {font-family : 'Davek';}
|
||||
&.Iokharic {font-family : 'Iokharic';}
|
||||
&.Rellanic {font-family : 'Rellanic';}
|
||||
&.TimesNewRoman {font-family : 'Times New Roman';}
|
||||
}
|
||||
}
|
||||
.name { margin-right : auto; }
|
||||
.disabled { text-decoration : line-through; }
|
||||
.beta {
|
||||
align-self : center;
|
||||
padding : 4px 6px;
|
||||
margin-left : 5px;
|
||||
font-family : monospace;
|
||||
line-height : 1em;
|
||||
color : white;
|
||||
background : grey;
|
||||
border-radius : 12px;
|
||||
}
|
||||
&:hover {
|
||||
background-color : #999999;
|
||||
}
|
||||
&:disabled {
|
||||
color: gray;
|
||||
cursor: not-allowed;
|
||||
&:hover { background-color: unset; }
|
||||
}
|
||||
}
|
||||
.disabledSnippets {
|
||||
color: grey;
|
||||
|
||||
@@ -44,7 +44,7 @@ const Homebrew = (props)=>{
|
||||
global.account = account;
|
||||
global.version = version;
|
||||
global.config = config;
|
||||
global.enablev4 = enablev4;
|
||||
global.enablev4 = enablev4;
|
||||
|
||||
const backgroundObject = ()=>{
|
||||
if(config?.deployment || (config?.local && config?.development)) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import Homebrew from './homebrew.jsx';
|
||||
import { bootstrapAnchorPositioningPolyfill } from '../components/anchorPositioningPolyfill.js';
|
||||
|
||||
const props = window.__INITIAL_PROPS__ || {};
|
||||
|
||||
createRoot(document.getElementById('reactRoot')).render(<Homebrew {...props} />);
|
||||
bootstrapAnchorPositioningPolyfill();
|
||||
|
||||
Generated
+1062
-1068
File diff suppressed because it is too large
Load Diff
@@ -105,6 +105,7 @@
|
||||
"@dmsnell/diff-match-patch": "^1.1.0",
|
||||
"@googleapis/drive": "^20.2.0",
|
||||
"@lezer/highlight": "^1.2.3",
|
||||
"@oddbird/css-anchor-positioning": "^0.9.0",
|
||||
"@sanity/diff-match-patch": "^3.2.0",
|
||||
"@vitejs/plugin-react": "^5.1.2",
|
||||
"body-parser": "^2.2.0",
|
||||
|
||||
@@ -21,3 +21,5 @@
|
||||
text-transform : unset;
|
||||
background-color : unset;
|
||||
}
|
||||
|
||||
:where(i){ text-box-trim: trim-both }
|
||||
|
||||
+16
-21
@@ -109,28 +109,24 @@ export default [
|
||||
gen : MonsterBlockGen.monster('monster,frame,wide', 4),
|
||||
},
|
||||
{
|
||||
name : 'Front Cover Page',
|
||||
icon : 'fac book-front-cover',
|
||||
gen : CoverPageGen.front,
|
||||
experimental : true
|
||||
name : 'Front Cover Page',
|
||||
icon : 'fac book-front-cover',
|
||||
gen : CoverPageGen.front,
|
||||
},
|
||||
{
|
||||
name : 'Inside Cover Page',
|
||||
icon : 'fac book-inside-cover',
|
||||
gen : CoverPageGen.inside,
|
||||
experimental : true
|
||||
name : 'Inside Cover Page',
|
||||
icon : 'fac book-inside-cover',
|
||||
gen : CoverPageGen.inside,
|
||||
},
|
||||
{
|
||||
name : 'Part Cover Page',
|
||||
icon : 'fac book-part-cover',
|
||||
gen : CoverPageGen.part,
|
||||
experimental : true
|
||||
name : 'Part Cover Page',
|
||||
icon : 'fac book-part-cover',
|
||||
gen : CoverPageGen.part,
|
||||
},
|
||||
{
|
||||
name : 'Back Cover Page',
|
||||
icon : 'fac book-back-cover',
|
||||
gen : CoverPageGen.back,
|
||||
experimental : true
|
||||
name : 'Back Cover Page',
|
||||
icon : 'fac book-back-cover',
|
||||
gen : CoverPageGen.back,
|
||||
},
|
||||
{
|
||||
name : 'Magic Item',
|
||||
@@ -209,11 +205,10 @@ export default [
|
||||
]
|
||||
},
|
||||
{
|
||||
name : 'Rune Table',
|
||||
icon : 'fas fa-language',
|
||||
gen : scriptGen.dwarvish,
|
||||
experimental : true,
|
||||
subsnippets : [
|
||||
name : 'Rune Table',
|
||||
icon : 'fas fa-language',
|
||||
gen : scriptGen.dwarvish,
|
||||
subsnippets : [
|
||||
{
|
||||
name : 'Dwarvish',
|
||||
icon : 'fac davek',
|
||||
|
||||
@@ -195,10 +195,9 @@ export default [
|
||||
]
|
||||
},
|
||||
{
|
||||
name : 'Index',
|
||||
icon : 'fas fa-bars',
|
||||
gen : indexGen,
|
||||
experimental : true
|
||||
name : 'Index',
|
||||
icon : 'fas fa-bars',
|
||||
gen : indexGen,
|
||||
},
|
||||
|
||||
]
|
||||
@@ -330,7 +329,7 @@ export default [
|
||||
},
|
||||
{
|
||||
name : 'DTRPG Community Content',
|
||||
incon : 'fab fa-dtrpg',
|
||||
icon : null,
|
||||
subsnippets : [
|
||||
{
|
||||
name : 'Chronicle System Guild Colophon',
|
||||
@@ -520,13 +519,13 @@ export default [
|
||||
|
||||
{
|
||||
name : 'MIT License',
|
||||
icon : 'fas fa-mit',
|
||||
icon : null,
|
||||
gen : LicenseGen.mit,
|
||||
},
|
||||
|
||||
{
|
||||
name : 'Mongoose Publishing Fair Use',
|
||||
icon : 'fas fa-mongoosepub',
|
||||
icon : null,
|
||||
subsnippets : [
|
||||
{
|
||||
name : 'Long Form Fair Use',
|
||||
@@ -554,14 +553,14 @@ export default [
|
||||
|
||||
{
|
||||
name : 'ORC Notice',
|
||||
icon : 'fas fa-Paizo',
|
||||
icon : null,
|
||||
gen : LicenseGen.orc1,
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
name : 'Shadowdark',
|
||||
icon : 'fab fa-shadowdark',
|
||||
icon : null,
|
||||
subsnippets : [
|
||||
{
|
||||
name : 'Logos',
|
||||
|
||||
Reference in New Issue
Block a user