├── .gitignore
├── LICENSE.md
├── README.md
├── composer.json
├── index.css
├── index.js
├── index.php
├── package.json
├── postcss.config.js
└── src
├── FieldsBlock.vue
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS files
2 | .DS_Store
3 |
4 | # npm modules
5 | /node_modules
6 |
7 | # Composer files
8 | /vendor
9 |
10 | # Lock Files
11 | yarn.lock
12 | package-lock.json
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Jon Gacnik
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Kirby Fields Block
2 |
3 | Kirby [block preview](https://getkirby.com/docs/reference/plugins/extensions/blocks) plugin to directly render block fields, allowing for inline editing.
4 |
5 |
6 |
7 | ## Usage
8 |
9 | ### Block definition
10 |
11 | When creating a custom block in your blueprints, pass `preview: fields` to utilize this plugin
12 |
13 | ```yaml
14 | blockname:
15 | name: Block Name
16 | preview: fields # required
17 | wysiwyg: true # recommended
18 | fields:
19 | text:
20 | label: Text
21 | type: text
22 | ```
23 |
24 | Setting `wysiwyg: true` prevents drawer from automatically opening when creating a new block.
25 |
26 | ### Disable block title
27 |
28 | You can disable the block title bar by passing `label: false`
29 |
30 | ```yaml
31 | blockname:
32 | name: Block Name
33 | preview: fields
34 | wysiwyg: true
35 | label: false # disables block title bar
36 | fields:
37 | text:
38 | label: Text
39 | type: text
40 | ```
41 |
42 |
43 | Example
44 |
45 |
46 |
47 | ### Collapse/Expand block
48 |
49 | You can collapse or expand the block preview by clicking on the arrow icon or double clicking the block title bar.
50 |
51 | ## Notes
52 |
53 | - The block `icon` will appear in the title bar.
54 | - Currently does not support blocks with tabs.
55 |
56 | ## Installation
57 |
58 | ```
59 | composer require jg/kirby-fields-block
60 | ```
61 |
62 |
63 | Other installation methods
64 |
65 | ### Download
66 |
67 | Download and copy this repository to `/site/plugins/kirby-fields-block`.
68 |
69 | ### Git submodule
70 |
71 | ```
72 | git submodule add https://github.com/jongacnik/kirby-fields-block.git site/plugins/kirby-fields-block
73 | ```
74 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jg/kirby-fields-block",
3 | "description": "Kirby Fields Block",
4 | "type": "kirby-plugin",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Jon Gacnik",
9 | "email": "jon@folderstudio.com"
10 | }
11 | ],
12 | "require": {
13 | "getkirby/composer-installer": "^1.1"
14 | }
15 | }
--------------------------------------------------------------------------------
/index.css:
--------------------------------------------------------------------------------
1 |
2 | .k-block-fields-preview {
3 | margin: -0.75rem;
4 | overflow: hidden;
5 | border-radius: var(--rounded);
6 | }
7 | .k-block-fields-preview .k-block-title {
8 | padding: 0.75rem;
9 | background: #f7f7f7;
10 | }
11 | .k-block-fields-preview:not([data-hidden="true"]) .k-block-title {
12 | border-bottom: 1px solid rgba(0,0,0,.1);
13 | }
14 | .k-block-fields-preview .k-fields-block-toggle {
15 | margin-left: auto;
16 | cursor: pointer;
17 | }
18 | .k-block-fields-preview[data-hidden="true"] .k-fields-block-toggle {
19 | transform: scaleY(-1);
20 | }
21 | .k-block-fields-preview .k-form {
22 | padding: 1.25rem 1.5rem 1.5rem 1.5rem;
23 | }
24 |
25 | /**
26 | * Reset `.k-layout-column .k-empty` overrides
27 | */
28 | .k-block-fields-preview .k-empty {
29 | position: static !important;
30 | opacity: 1 !important;
31 | align-items: stretch !important;
32 | justify-content: flex-start !important;
33 | color: #777 !important;
34 | border: 1px dashed #ccc !important;
35 | border-radius: 1px !important;
36 | }
37 | .k-block-fields-preview .k-empty[data-layout="cards"] {
38 | justify-content: center !important;
39 | }
40 | .k-block-fields-preview .k-empty[data-layout="list"] .k-icon {
41 | border-right: 1px solid rgba(0,0,0,.05) !important;
42 | }
43 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | "use strict";
3 | const FieldsBlock_vue_vue_type_style_index_0_lang = "";
4 | function normalizeComponent(scriptExports, render, staticRenderFns, functionalTemplate, injectStyles, scopeId, moduleIdentifier, shadowMode) {
5 | var options = typeof scriptExports === "function" ? scriptExports.options : scriptExports;
6 | if (render) {
7 | options.render = render;
8 | options.staticRenderFns = staticRenderFns;
9 | options._compiled = true;
10 | }
11 | if (functionalTemplate) {
12 | options.functional = true;
13 | }
14 | if (scopeId) {
15 | options._scopeId = "data-v-" + scopeId;
16 | }
17 | var hook;
18 | if (moduleIdentifier) {
19 | hook = function(context) {
20 | context = context || this.$vnode && this.$vnode.ssrContext || this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext;
21 | if (!context && typeof __VUE_SSR_CONTEXT__ !== "undefined") {
22 | context = __VUE_SSR_CONTEXT__;
23 | }
24 | if (injectStyles) {
25 | injectStyles.call(this, context);
26 | }
27 | if (context && context._registeredComponents) {
28 | context._registeredComponents.add(moduleIdentifier);
29 | }
30 | };
31 | options._ssrRegister = hook;
32 | } else if (injectStyles) {
33 | hook = shadowMode ? function() {
34 | injectStyles.call(
35 | this,
36 | (options.functional ? this.parent : this).$root.$options.shadowRoot
37 | );
38 | } : injectStyles;
39 | }
40 | if (hook) {
41 | if (options.functional) {
42 | options._injectStyles = hook;
43 | var originalRender = options.render;
44 | options.render = function renderWithStyleInjection(h, context) {
45 | hook.call(context);
46 | return originalRender(h, context);
47 | };
48 | } else {
49 | var existing = options.beforeCreate;
50 | options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
51 | }
52 | }
53 | return {
54 | exports: scriptExports,
55 | options
56 | };
57 | }
58 | const _sfc_main = {
59 | data() {
60 | return {
61 | isHidden: JSON.parse(sessionStorage.getItem(`kirby.fieldsBlock.${this.$attrs.endpoints.field}.${this.$attrs.id}`))
62 | };
63 | },
64 | methods: {
65 | toggle() {
66 | this.isHidden = !this.isHidden;
67 | sessionStorage.setItem(`kirby.fieldsBlock.${this.$attrs.endpoints.field}.${this.$attrs.id}`, this.isHidden);
68 | },
69 | preventSelect(event) {
70 | if (event.detail > 1) {
71 | if (!event.target.closest(".k-input")) {
72 | event.preventDefault();
73 | }
74 | }
75 | }
76 | }
77 | };
78 | var _sfc_render = function render() {
79 | var _vm = this, _c = _vm._self._c;
80 | return _c("div", { staticClass: "k-block-fields-preview", attrs: { "data-hidden": _vm.isHidden }, on: { "mousedown": _vm.preventSelect } }, [_vm.fieldset.label === null || _vm.fieldset.label ? _c("k-fields-block-title", { attrs: { "content": _vm.content, "fieldset": _vm.fieldset }, on: { "dblclick": _vm.toggle, "toggle": _vm.toggle } }) : _vm._e(), !_vm.isHidden ? _c("k-form", { ref: "form", attrs: { "autofocus": true, "fields": _vm.fieldset.tabs.content.fields, "value": _vm.$helper.clone(_vm.content) }, on: { "input": function($event) {
81 | return _vm.$emit("update", $event);
82 | } } }) : _vm._e()], 1);
83 | };
84 | var _sfc_staticRenderFns = [];
85 | _sfc_render._withStripped = true;
86 | var __component__ = /* @__PURE__ */ normalizeComponent(
87 | _sfc_main,
88 | _sfc_render,
89 | _sfc_staticRenderFns,
90 | false,
91 | null,
92 | null,
93 | null,
94 | null
95 | );
96 | __component__.options.__file = "/Users/jongacnik/Sites/_kirby/kirby-fields-block/src/FieldsBlock.vue";
97 | const FieldsBlock = __component__.exports;
98 | panel.plugin("jg/fields-block", {
99 | components: {
100 | "k-fields-block-title": {
101 | extends: "k-block-title",
102 | template: `
103 |
104 |
105 |
106 | {{ name }}
107 |
108 |
109 | {{ label }}
110 |
111 |
112 |
113 |
114 |
115 | `
116 | }
117 | },
118 | blocks: {
119 | fields: FieldsBlock
120 | }
121 | });
122 | })();
123 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | ",
7 | "license": "MIT",
8 | "devDependencies": {
9 | "kirbyup": "latest"
10 | },
11 | "scripts": {
12 | "dev": "kirbyup src/index.js --watch",
13 | "build": "kirbyup src/index.js"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: { }
3 | }
--------------------------------------------------------------------------------
/src/FieldsBlock.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
18 |
19 |
20 |
21 |
43 |
44 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import FieldsBlock from "./FieldsBlock.vue"
2 |
3 | panel.plugin("jg/fields-block", {
4 | components: {
5 | 'k-fields-block-title': {
6 | extends: 'k-block-title',
7 | template: `
8 |
9 |
10 |
11 | {{ name }}
12 |
13 |
14 | {{ label }}
15 |
16 |
17 |
18 |
19 |
20 | `
21 | }
22 | },
23 | blocks: {
24 | fields: FieldsBlock
25 | }
26 | })
--------------------------------------------------------------------------------