From cd1ddf9acd6e33d9f50c72d3b229462d71efcff7 Mon Sep 17 00:00:00 2001 From: linonetwo Date: Sun, 19 Feb 2023 15:58:14 +0800 Subject: [PATCH] feat: config theme for super tag --- .../TraitTags/$__TraitTag_ActionState.json | 6 +-- .../tiddlers/TraitTags/$__TraitTag_Color.json | 2 +- package.json | 4 +- pnpm-lock.yaml | 6 +++ src/type.d.ts | 6 ++- src/widgets/supertag-form/index.css.meta | 2 +- src/widgets/supertag-form/index.js.meta | 2 +- src/widgets/supertag-form/index.ts | 52 +++++++++++++++++-- src/widgets/supertag-form/style.css | 44 ++++++++++++++++ src/widgets/supertag-form/usePalette.tid | 18 +++++++ src/widgets/supertag-form/widget-loader.js | 2 +- .../supertag-form/widget-loader.js.meta | 2 +- 12 files changed, 131 insertions(+), 15 deletions(-) create mode 100644 src/widgets/supertag-form/style.css create mode 100644 src/widgets/supertag-form/usePalette.tid diff --git a/demo/tiddlers/TraitTags/$__TraitTag_ActionState.json b/demo/tiddlers/TraitTags/$__TraitTag_ActionState.json index 32fe8e3..41219bc 100644 --- a/demo/tiddlers/TraitTags/$__TraitTag_ActionState.json +++ b/demo/tiddlers/TraitTags/$__TraitTag_ActionState.json @@ -4,12 +4,12 @@ "creator": "林一二", "text": "Describe action like task's complete state.", "title": "$:/TraitTag/ActionState", - "modified": "20230218103100729", + "modified": "20230219063009765", "modifier": "林一二", "tags": "$:/SuperTag/TraitTag", "type": "text/vnd.tiddlywiki", - "schema": "{\n \"type\": \"object\",\n \"properties\": {\n \"completed\": {\n \"type\": \"boolean\"\n },\n \"completeType\": {\n \"type\": \"string\",\n \"enum\": [\"Delay\", \"AtTime\", \"InAdvance\"]\n },\n \"completedCount\": {\n \"type\": \"number\"\n }\n }\n}\n", - "wl-field-name-text": "uiSchema", + "schema": "{\n \"type\": \"object\",\n \"properties\": {\n \"completed\": {\n \"type\": \"boolean\"\n },\n \"completeType\": {\n \"type\": \"string\",\n \"enum\": [\"Delay\", \"AtTime\", \"InAdvance\"]\n },\n \"completedCount\": {\n \"type\": \"number\"\n }\n },\n \"required\": [\"completed\"]\n}\n", + "wl-field-name-text": "schema", "uiSchema": "{\n \"type\": \"VerticalLayout\",\n \"elements\": [\n {\n \"type\": \"Control\",\n \"scope\": \"#/properties/completed\"\n },\n {\n \"type\": \"Control\",\n \"scope\": \"#/properties/completeType\"\n },\n {\n \"type\": \"Control\",\n \"scope\": \"#/properties/completedCount\"\n }\n ]\n}" } ] \ No newline at end of file diff --git a/demo/tiddlers/TraitTags/$__TraitTag_Color.json b/demo/tiddlers/TraitTags/$__TraitTag_Color.json index 1e10e57..1c201a0 100644 --- a/demo/tiddlers/TraitTags/$__TraitTag_Color.json +++ b/demo/tiddlers/TraitTags/$__TraitTag_Color.json @@ -7,7 +7,7 @@ "tags": "$:/SuperTag/TraitTag", "type": "text/vnd.tiddlywiki", "wl-field-name-text": "schema", - "schema": "{\n \"type\": \"object\",\n \"properties\": {\n \"string\": {\n \"type\": \"string\"\n }\n }\n}", + "schema": "{\n \"type\": \"object\",\n \"properties\": {\n \"color\": {\n \"type\": \"string\",\n \"format\": \"color\"\n}\n }\n}", "uiSchema": "{\n \"type\": \"VerticalLayout\",\n \"elements\": [\n {\n \"type\": \"Control\",\n \"scope\": \"#/properties/string\"\n }\n ]\n}" } ] \ No newline at end of file diff --git a/package.json b/package.json index 940671e..383f161 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ ], "ignoredExtensionsWhenBuildPlugin": [ ".ts", + ".css", ".tsx", ".snap", ".tldr", @@ -82,6 +83,7 @@ "zx": "7.1.1" }, "dependencies": { - "@json-editor/json-editor": "2.9.0-beta.1" + "@json-editor/json-editor": "2.9.0-beta.1", + "spectre.css": "^0.5.9" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8e2e3b6..43e7af9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,6 +45,7 @@ specifiers: prettier: 2.8.4 rimraf: ^4.1.2 serve: 14.2.0 + spectre.css: ^0.5.9 tiddlywiki: 5.2.5 ts-jest: 29.0.5 tslib: 2.5.0 @@ -57,6 +58,7 @@ specifiers: dependencies: '@json-editor/json-editor': 2.9.0-beta.1 + spectre.css: 0.5.9 devDependencies: '@types/archiver': 5.3.1 @@ -5336,6 +5338,10 @@ packages: resolution: {integrity: sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==} dev: true + /spectre.css/0.5.9: + resolution: {integrity: sha512-9jUqwZmCnvflrxFGcK+ize43TvjwDjqMwZPVubEtSIHzvinH0TBUESm1LcOJx3Ur7bdPaeOHQIjOqBl1Y5kLFw==} + dev: false + /split/0.3.3: resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} dependencies: diff --git a/src/type.d.ts b/src/type.d.ts index eca2d71..c481641 100644 --- a/src/type.d.ts +++ b/src/type.d.ts @@ -42,7 +42,7 @@ declare module '@json-editor/json-editor' { /** * The icon library to use for the editor. */ - iconlib?: 'bootstrap2' | 'bootstrap3' | 'foundation2' | 'foundation3' | 'jqueryui' | 'fontawesome3' | 'fontawesome4' | undefined; + iconlib?: 'jqueryui' | 'fontawesome3' | 'fontawesome4' | 'fontawesome5' | 'openiconic' | 'spectre' | undefined; /** * If true, makes oneOf copy properties over when switching. */ @@ -79,6 +79,10 @@ declare module '@json-editor/json-editor' { * The CSS theme to use. */ theme?: 'barebones' | 'html' | 'bootstrap4' | 'bootstrap5' | 'spectre' | 'tailwind' | undefined; + /** + * If true default values based on the "type" of the property will be used + */ + use_default_values?: boolean | undefined; } interface JSONEditorError { message: string; diff --git a/src/widgets/supertag-form/index.css.meta b/src/widgets/supertag-form/index.css.meta index 1cf3d3e..6fb4a7d 100644 --- a/src/widgets/supertag-form/index.css.meta +++ b/src/widgets/supertag-form/index.css.meta @@ -1,3 +1,3 @@ -title: $:/themes/linonetwo/intention-tower-knowledge-graph/widgets/supertag-form.css +title: $:/plugins/linonetwo/super-tag/widgets/supertag-form/index.css tags: $:/tags/Stylesheet type: text/css \ No newline at end of file diff --git a/src/widgets/supertag-form/index.js.meta b/src/widgets/supertag-form/index.js.meta index a73c1aa..7fd600f 100644 --- a/src/widgets/supertag-form/index.js.meta +++ b/src/widgets/supertag-form/index.js.meta @@ -1,5 +1,5 @@ creator: LinOnetwo -title: $:/plugins/linonetwo/super-tag/widgets/supertag-form.js +title: $:/plugins/linonetwo/super-tag/widgets/supertag-form/index.js type: application/javascript module-type: library hide-body: yes \ No newline at end of file diff --git a/src/widgets/supertag-form/index.ts b/src/widgets/supertag-form/index.ts index 5c633ce..2f3e026 100644 --- a/src/widgets/supertag-form/index.ts +++ b/src/widgets/supertag-form/index.ts @@ -1,7 +1,9 @@ import type { IChangedTiddlers } from 'tiddlywiki'; import * as JSONEditor from '@json-editor/json-editor'; -import '@json-editor/json-editor/src/themes/bootstrap5.css'; -import type { JSONSchema4 } from 'json-schema'; +import 'spectre.css/dist/spectre.min.css'; +import 'spectre.css/dist/spectre-icons.css'; +import 'spectre.css/dist/spectre-exp.css'; +import './style.css'; import { widget as Widget } from '$:/core/modules/widgets/widget.js'; import { getSuperTagTraits } from '../utils/getTraits'; import { mergeSchema } from '../utils/mergeSchema'; @@ -9,6 +11,8 @@ import { mergeSchema } from '../utils/mergeSchema'; class SupertagFormWidget extends Widget { editor?: JSONEditor.JSONEditor; containerElement?: HTMLDivElement; + errorValidatorInfoElement?: HTMLSpanElement; + currentTiddlerTitle?: string; refresh(_changedTiddlers: IChangedTiddlers): boolean { return false; @@ -21,23 +25,61 @@ class SupertagFormWidget extends Widget { this.parentDomNode = parent; this.computeAttributes(); this.execute(); + const currentTiddlerTitle = this.getAttribute('tiddler') ?? this.getVariable('currentTiddler'); + this.currentTiddlerTitle = currentTiddlerTitle; if (this.editor === undefined) { const containerElement = document.createElement('div'); + const editorElement = document.createElement('div'); + const errorValidatorInfoElement = document.createElement('span'); + this.errorValidatorInfoElement = errorValidatorInfoElement; this.containerElement = containerElement; + containerElement.appendChild(editorElement); + containerElement.appendChild(errorValidatorInfoElement); this.domNodes.push(containerElement); // eslint-disable-next-line unicorn/prefer-dom-node-append parent.appendChild(containerElement); - const currentTiddlerTitle = this.getVariable('currentTiddler'); const superTags = getSuperTagTraits(currentTiddlerTitle); + const tiddlerFields = $tw.wiki.getTiddler(currentTiddlerTitle)?.fields ?? {}; if (superTags.length === 0) return; const fullSchema = mergeSchema(superTags); - this.editor = new JSONEditor.JSONEditor(containerElement, { + this.editor = new JSONEditor.JSONEditor(editorElement, { schema: fullSchema, - theme: 'bootstrap5', + theme: 'spectre', + iconlib: 'spectre', + disable_edit_json: true, + form_name_root: 'SuperTag', + startval: tiddlerFields, + no_additional_properties: true, + use_default_values: true, }); + this.editor.on('change', this.formOnChange); } } + + private readonly formOnChange = () => { + if (this.editor === undefined) return; + const latestFormValue = this.editor?.getValue() as Record; + if (this.currentTiddlerTitle !== undefined && latestFormValue !== undefined && latestFormValue !== null && this.errorValidatorInfoElement !== undefined) { + // Get an array of errors from the validator + const errors = this.editor.validate(); + if (errors.length > 0) { + this.errorValidatorInfoElement.className = 'label label-warning'; + this.errorValidatorInfoElement.textContent = 'Form not valid'; + } else { + const tiddlerFields = $tw.wiki.getTiddler(this.currentTiddlerTitle)?.fields ?? {}; + $tw.wiki.addTiddler({ ...tiddlerFields, ...latestFormValue, title: this.currentTiddlerTitle }); + } + } + }; + + removeChildDomNodes(): void { + this.editor?.off('change', this.formOnChange); + this.editor?.destroy(); + this.editor = undefined; + this.containerElement = undefined; + this.errorValidatorInfoElement = undefined; + } } declare const exports: Record; diff --git a/src/widgets/supertag-form/style.css b/src/widgets/supertag-form/style.css new file mode 100644 index 0000000..b50f8f4 --- /dev/null +++ b/src/widgets/supertag-form/style.css @@ -0,0 +1,44 @@ +.je-object__container { + display: flex; + flex-direction: row; + align-items: center; + /* Use grid in supported browser */ + display: grid; +} +.je-object__container .btn:last-child:not(:first-child) { + margin: unset; + border-radius: 0; +} +.je-object__container button.json-editor-btn-edit_properties.json-editor-btntype-properties { + /* overwrite mr-2 */ + margin: 0 !important; +} +h4.je-object__title { + margin: 0; + /* margin extra space in flex group when grid not working */ + margin-right: 5px; + font-size: 1.2em; + white-space: nowrap; +} +h4.je-object__title > .json-editor-btn-collapse { + margin-left: 0; +} +.btn-group.je-object__controls { + margin: 0; +} + +div[data-theme='spectre'] div.je-panel { + margin: 0; + padding: 0; +} +.je-panel > div.container { + padding: 0; +} +.je-panel > div.container > div { + display: flex; + flex-direction: row; + flex-wrap: wrap; +} +.je-panel > div.container > div > .columns { + margin: unset; +} diff --git a/src/widgets/supertag-form/usePalette.tid b/src/widgets/supertag-form/usePalette.tid new file mode 100644 index 0000000..2517477 --- /dev/null +++ b/src/widgets/supertag-form/usePalette.tid @@ -0,0 +1,18 @@ +title: $:/plugins/linonetwo/super-tag/widgets/supertag-form/usePalette.css +tags: $:/tags/Stylesheet +type: text/vnd.tiddlywiki + +<$importvariables filter="[[$:/themes/tiddlywiki/vanilla/base]]"> + +button.btn.btn-primary { + background: <>; + border-color:<>; + color: <>; +} +button.btn.btn-primary:hover { + background-color: <>; + border-color:<>; + color: <>; +} + + \ No newline at end of file diff --git a/src/widgets/supertag-form/widget-loader.js b/src/widgets/supertag-form/widget-loader.js index 5d654da..76b0690 100644 --- a/src/widgets/supertag-form/widget-loader.js +++ b/src/widgets/supertag-form/widget-loader.js @@ -5,7 +5,7 @@ return; } // separate the widget from the exports here, so we can skip the require of react code if `!$tw.browser`. Those ts code will error if loaded in the nodejs side. - const components = require('$:/plugins/linonetwo/super-tag/widgets/supertag-form.js'); + const components = require('$:/plugins/linonetwo/super-tag/widgets/supertag-form/index.js'); const { 'supertag-form': SupertagFormWidget } = components; // declare const exports: Record; exports['supertag-form'] = SupertagFormWidget; diff --git a/src/widgets/supertag-form/widget-loader.js.meta b/src/widgets/supertag-form/widget-loader.js.meta index 3e3bc58..7506a67 100644 --- a/src/widgets/supertag-form/widget-loader.js.meta +++ b/src/widgets/supertag-form/widget-loader.js.meta @@ -1,3 +1,3 @@ -title: $:/plugins/linonetwo/super-tag/supertag-form-widget-loader.js +title: $:/plugins/linonetwo/super-tag/supertag-form/widget-loader.js type: application/javascript module-type: widget \ No newline at end of file