enhance iconify usage and tune editor styles
This commit is contained in:
parent
3c8ac17617
commit
0a28944eea
|
|
@ -1,11 +1,64 @@
|
|||
@mixin button-base {
|
||||
appearance: none;
|
||||
user-select: none;
|
||||
vertical-align: middle;
|
||||
outline: 0;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@mixin normal-button {
|
||||
@include button-base;
|
||||
|
||||
background-color: #eee;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 2px;
|
||||
padding: 0px 8px;
|
||||
line-height: 22px;
|
||||
|
||||
&:hover {
|
||||
background-color: #e1e1e1;
|
||||
}
|
||||
&:active {
|
||||
border-color: #555;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin text-button {
|
||||
@include button-base;
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
color: #555;
|
||||
&:hover {
|
||||
border-bottom: 1px solid #999;
|
||||
}
|
||||
&:active {
|
||||
border-color: transparent;
|
||||
border-bottom: 1px solid #000;
|
||||
}
|
||||
}
|
||||
|
||||
.editor-container {
|
||||
font-size: 14px;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
--gap: 8px;
|
||||
--blue-0: #D0EBFF;
|
||||
--blue-1: #A5D8FF;
|
||||
--red-0: #FFE3E3;
|
||||
--red-1: #FFC9C9;
|
||||
--yellow-0: #FFF3BF;
|
||||
--yellow-1: #FFEC99;
|
||||
--green-0: #D3F9D8;
|
||||
--green-1: #B2F2BB;
|
||||
|
||||
h1 {}
|
||||
h2 {}
|
||||
h3 {}
|
||||
h3 {
|
||||
margin: 12px 0 12px 0;
|
||||
}
|
||||
p {
|
||||
margin: 0 0 var(--gap) 0;
|
||||
}
|
||||
|
|
@ -18,12 +71,46 @@
|
|||
line-height: 1.3;
|
||||
padding: var(--gap);
|
||||
}
|
||||
input[type=text],
|
||||
input[type=email],
|
||||
textarea {
|
||||
border: 1px solid #888;
|
||||
border-radius: 2px;
|
||||
}
|
||||
button {
|
||||
@include normal-button;
|
||||
|
||||
margin-right: var(--gap);
|
||||
// last-of-type should not be used here
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
bottom: 1px;
|
||||
}
|
||||
}
|
||||
iconify-icon {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.je-header {
|
||||
label {
|
||||
font-weight: 700;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
// override theme-default
|
||||
.je-indented-panel {
|
||||
padding-left: var(--gap);
|
||||
margin-left: var(--gap);
|
||||
border-left: 1px solid #ccc
|
||||
padding-left: calc(var(--gap) * 2);
|
||||
padding-bottom: var(--gap);
|
||||
margin-left: 0;
|
||||
border-left: 1px solid #ddd;
|
||||
margin-bottom: var(--gap);
|
||||
}
|
||||
|
||||
.je-indented-panel--top {
|
||||
|
|
@ -31,10 +118,6 @@
|
|||
margin-left: var(--gap);
|
||||
}
|
||||
|
||||
.je-object__container {
|
||||
|
||||
}
|
||||
|
||||
.form-control {
|
||||
margin-bottom: var(--gap);
|
||||
}
|
||||
|
|
@ -42,7 +125,7 @@
|
|||
.je-form-input-label {
|
||||
display: block;
|
||||
margin-bottom: calc(var(--gap) / 2);
|
||||
font-weight: bold;
|
||||
font-weight: 500;
|
||||
}
|
||||
.je-form-input-description {
|
||||
margin: 0;
|
||||
|
|
@ -63,6 +146,36 @@
|
|||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
/* buttons */
|
||||
.je-object__controls {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin-left: calc(var(--gap) * 2);
|
||||
top: 2px;
|
||||
|
||||
button {
|
||||
@include text-button;
|
||||
}
|
||||
}
|
||||
.json-editor-btn-add {
|
||||
background-color: var(--green-0);
|
||||
&:hover {
|
||||
background-color: var(--green-1);
|
||||
}
|
||||
}
|
||||
.json-editor-btn-subtract {
|
||||
background-color: var(--yellow-0);
|
||||
&:hover {
|
||||
background-color: var(--yellow-1);
|
||||
}
|
||||
}
|
||||
.json-editor-btn-delete {
|
||||
background-color: var(--red-0);
|
||||
&:hover {
|
||||
background-color: var(--red-1);
|
||||
}
|
||||
}
|
||||
|
||||
.je-textarea {
|
||||
height: 150px;
|
||||
min-height: 150px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
import { AbstractIconLib } from '@json-editor/json-editor/src/iconlib.js';
|
||||
|
||||
import { getIconSVG } from '../icons';
|
||||
|
||||
const iconMapping = {
|
||||
collapse: 'mdi:chevron-down',
|
||||
expand: 'mdi:chevron-right',
|
||||
delete: 'mdi:delete',
|
||||
edit: 'mdi:pen',
|
||||
add: 'mdi:plus',
|
||||
subtract: 'mdi:minus',
|
||||
cancel: 'mdi:cancel',
|
||||
save: 'mdi:content-save',
|
||||
moveup: 'mdi:arrow-up',
|
||||
moveright: 'mdi:arrow-right',
|
||||
movedown: 'mdi:arrow-down',
|
||||
moveleft: 'mdi:arrow-left',
|
||||
copy: 'mdi:content-copy',
|
||||
clear: 'mdi:close-circle',
|
||||
time: 'mdi:clock',
|
||||
calendar: 'mdi:calendar',
|
||||
edit_properties: 'mdi:format-list-bulleted',
|
||||
}
|
||||
|
||||
|
||||
export class MyIconLib extends AbstractIconLib {
|
||||
|
||||
getIcon(key) {
|
||||
const svg = getIconSVG(iconMapping[key], {dom: true})
|
||||
return svg
|
||||
// const i = document.createElement('iconify-icon')
|
||||
// i.setAttribute('icon', )
|
||||
// return i
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export function registerIconLib(JSONEditor) {
|
||||
JSONEditor.defaults.iconlibs['myiconlib'] = MyIconLib
|
||||
}
|
||||
|
|
@ -1,11 +1,17 @@
|
|||
import 'iconify-icon'; // import only
|
||||
|
||||
import objectPath from 'object-path';
|
||||
|
||||
import { JSONEditor } from '@json-editor/json-editor/dist/jsoneditor';
|
||||
|
||||
import * as exampleData from '../sample.resume.json';
|
||||
import * as jsoncvSchema from '../schema/jsoncv.schema.json';
|
||||
import * as jsoncvSchemaModule from '../schema/jsoncv.schema.json';
|
||||
import { registerIconLib } from './iconlib';
|
||||
import { registerTheme } from './theme';
|
||||
import { createElement } from './utils';
|
||||
import {
|
||||
createElement,
|
||||
traverseDownObject,
|
||||
} from './utils';
|
||||
|
||||
const propertiesInOrder = ['basics', 'education', 'work', 'skills', 'projects', 'languages', 'interests', 'references', 'awards', 'publications', 'volunteer']
|
||||
const basicsPropertiesInOrder = ['name', 'label', 'email', 'phone', 'url', 'summary', 'image', 'location', 'profiles']
|
||||
|
|
@ -19,7 +25,9 @@ const basicsUl = createElement('ul', {
|
|||
parent: tocUl
|
||||
})
|
||||
|
||||
const attrSchemaPathTo = 'data-schemapath-to'
|
||||
|
||||
// copy the object to remove the readonly restriction on module
|
||||
const jsoncvSchema = {...jsoncvSchemaModule.default}
|
||||
|
||||
// add propertyOrder to schema, and add links to toc
|
||||
propertiesInOrder.forEach((name, index) => {
|
||||
|
|
@ -50,6 +58,15 @@ basicsPropertiesInOrder.forEach((name, index) => {
|
|||
})
|
||||
})
|
||||
|
||||
// add headerTemplate for each type:array in schema
|
||||
traverseDownObject(jsoncvSchema, (key, obj) => {
|
||||
let noun = key
|
||||
if (noun.endsWith('s')) noun = noun.slice(0, -1)
|
||||
if (obj.type === 'array' && obj.items) {
|
||||
obj.items.headerTemplate = `${noun} {{i1}}`
|
||||
}
|
||||
})
|
||||
|
||||
// add format to schema
|
||||
const keyFormatMap = {
|
||||
'basics.properties.summary': 'textarea',
|
||||
|
|
@ -58,12 +75,17 @@ for (const [key, format] of Object.entries(keyFormatMap)) {
|
|||
objectPath.get(jsoncvSchema.properties, key).format = format
|
||||
}
|
||||
|
||||
// change schema title
|
||||
jsoncvSchema.title = 'Resume'
|
||||
|
||||
// initialize editor
|
||||
registerTheme(JSONEditor)
|
||||
registerIconLib(JSONEditor)
|
||||
const elEditorContainer = document.querySelector('.editor-container')
|
||||
const editor = new JSONEditor(elEditorContainer, {
|
||||
schema: jsoncvSchema,
|
||||
theme: 'mytheme',
|
||||
iconlib: 'myiconlib',
|
||||
});
|
||||
editor.on('ready',() => {
|
||||
editor.setValue(exampleData)
|
||||
|
|
@ -72,6 +94,5 @@ editor.on('ready',() => {
|
|||
document.querySelectorAll('[data-schemapath]').forEach(el => {
|
||||
const schemapath = el.getAttribute('data-schemapath')
|
||||
el.id = schemapath
|
||||
console.log('el', schemapath)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -14,3 +14,13 @@ export const createElement = function(tagName, {className, text, attrs, parent})
|
|||
}
|
||||
return el
|
||||
}
|
||||
|
||||
export const traverseDownObject = function(obj, callback) {
|
||||
for (const key in obj) {
|
||||
const value = obj[key]
|
||||
if (typeof value === 'object') {
|
||||
callback(key, value)
|
||||
traverseDownObject(value, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,10 +8,11 @@
|
|||
"name": "jsoncv",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@iconify/json": "^2.2.15",
|
||||
"ajv": "^8.12.0",
|
||||
"ajv-formats": "^2.1.1",
|
||||
"dayjs": "^1.11.7",
|
||||
"iconify-icon": "^1.0.0",
|
||||
"iconify-icon": "^1.0.3",
|
||||
"object-path": "^0.11.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -86,6 +87,15 @@
|
|||
"@iconify/types": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@iconify/json": {
|
||||
"version": "2.2.15",
|
||||
"resolved": "https://registry.npmjs.org/@iconify/json/-/json-2.2.15.tgz",
|
||||
"integrity": "sha512-+BVLIjTJpBiEOGD3xhCY7/ajH+7QTl/jzF59gf9Hf5y/HyU8D+HUmOsXEGLIsCZErEQB66wZ36AziOlYf3wuPA==",
|
||||
"dependencies": {
|
||||
"@iconify/types": "*",
|
||||
"pathe": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@iconify/types": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
|
||||
|
|
@ -847,14 +857,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/iconify-icon": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/iconify-icon/-/iconify-icon-1.0.0.tgz",
|
||||
"integrity": "sha512-UY4PDCKQPpIGgDIx2yxM8wiOdMdLz0mb93dTV0Ox5hThwO8OA2zy8gDmjRReKqkPHK/mY7p/ivDaDGHE8O9xIw==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/iconify-icon/-/iconify-icon-1.0.3.tgz",
|
||||
"integrity": "sha512-pyWLbx8IBfD2G3M0hULuvUBwoowrZtXEKyeAXhD2AlbNYTSDPmWGhgPYaRAnVIuBjMAZ4dCyEHmaYgnlDZc0XQ==",
|
||||
"dependencies": {
|
||||
"@iconify/types": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "http://github.com/sponsors/cyberalien"
|
||||
"url": "https://github.com/sponsors/cyberalien"
|
||||
}
|
||||
},
|
||||
"node_modules/immutable": {
|
||||
|
|
@ -1196,6 +1206,11 @@
|
|||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/pathe": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz",
|
||||
"integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w=="
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
|
|
@ -1975,6 +1990,15 @@
|
|||
"@iconify/types": "*"
|
||||
}
|
||||
},
|
||||
"@iconify/json": {
|
||||
"version": "2.2.15",
|
||||
"resolved": "https://registry.npmjs.org/@iconify/json/-/json-2.2.15.tgz",
|
||||
"integrity": "sha512-+BVLIjTJpBiEOGD3xhCY7/ajH+7QTl/jzF59gf9Hf5y/HyU8D+HUmOsXEGLIsCZErEQB66wZ36AziOlYf3wuPA==",
|
||||
"requires": {
|
||||
"@iconify/types": "*",
|
||||
"pathe": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"@iconify/types": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
|
||||
|
|
@ -2436,9 +2460,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"iconify-icon": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/iconify-icon/-/iconify-icon-1.0.0.tgz",
|
||||
"integrity": "sha512-UY4PDCKQPpIGgDIx2yxM8wiOdMdLz0mb93dTV0Ox5hThwO8OA2zy8gDmjRReKqkPHK/mY7p/ivDaDGHE8O9xIw==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/iconify-icon/-/iconify-icon-1.0.3.tgz",
|
||||
"integrity": "sha512-pyWLbx8IBfD2G3M0hULuvUBwoowrZtXEKyeAXhD2AlbNYTSDPmWGhgPYaRAnVIuBjMAZ4dCyEHmaYgnlDZc0XQ==",
|
||||
"requires": {
|
||||
"@iconify/types": "^2.0.0"
|
||||
}
|
||||
|
|
@ -2692,6 +2716,11 @@
|
|||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"dev": true
|
||||
},
|
||||
"pathe": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz",
|
||||
"integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w=="
|
||||
},
|
||||
"picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@
|
|||
"vite-plugin-handlebars": "^1.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify/json": "^2.2.15",
|
||||
"ajv": "^8.12.0",
|
||||
"ajv-formats": "^2.1.1",
|
||||
"dayjs": "^1.11.7",
|
||||
"iconify-icon": "^1.0.0",
|
||||
"iconify-icon": "^1.0.3",
|
||||
"object-path": "^0.11.8"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue