Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions resources/css/components/fieldtypes/bard.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
/* BARD
=================================================== */

.bard-bulk-op [data-type] header,
.bard-bulk-op [data-type] header * {
transition: none !important;
}

@layer ui {
/* .grid-cell, [data-ui-input-group] are exceptions for Bard fieldtypes inside a Grid fieldtype, since these cause double borders */
.bard-fieldtype:not(.form-group, .grid-cell, [data-ui-input-group]) {
Expand Down
5 changes: 5 additions & 0 deletions resources/css/components/fieldtypes/replicator.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/* ==========================================================================
REPLICATOR FIELDTYPE
========================================================================== */

.replicator-bulk-op [data-replicator-set] header,
.replicator-bulk-op [data-replicator-set] header * {
transition: none !important;
}
8 changes: 5 additions & 3 deletions resources/js/bootstrap/statamic.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,11 @@ export default {
const bladeContent = el?.innerHTML || '';
const _this = this;

const corePages = import.meta.glob('../pages/**/*.vue');

await createInertiaApp({
id: 'statamic',
resolve: name => {
resolve: async name => {
if (name === 'NonInertiaPage') {
return {
default: {
Expand All @@ -211,8 +213,8 @@ export default {
}

// Resolve core pages
const pages = import.meta.glob('../pages/**/*.vue', { eager: true });
let page = pages[`../pages/${name}.vue`];
const pageImport = corePages[`../pages/${name}.vue`];
let page = pageImport ? await pageImport() : null;

// Resolve addon pages
if (!page) {
Expand Down
10 changes: 9 additions & 1 deletion resources/js/components/field-actions/HasFieldActions.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import toFieldActions from './toFieldActions.js';

export default {
data() {
return {
_cachedFieldActions: null,
};
},

computed: {
fieldActions() {
return toFieldActions(
if (this._cachedFieldActions) return this._cachedFieldActions;
this._cachedFieldActions = toFieldActions(
this.fieldActionBinding,
this.fieldActionPayload,
this.internalFieldActions,
);
return this._cachedFieldActions;
},

internalFieldActions() {
Expand Down
3 changes: 2 additions & 1 deletion resources/js/components/field-actions/toFieldActions.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { markRaw } from 'vue';
import FieldAction from './FieldAction.js';

export default function toFieldActions(binding, payload, extraActions = []) {
return [...Statamic.$fieldActions.get(binding), ...extraActions]
.map((action) => new FieldAction(action, payload))
.map((action) => markRaw(new FieldAction(action, payload)))
.filter((action) => action.visible);
}
31 changes: 25 additions & 6 deletions resources/js/components/fieldtypes/Fieldtype.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,31 @@ export default {
// When using the Options API, this feels more natural. However since this is a
// computed, it won't be avaialble within data(). In those cases you will
// need to use this.injectedPublishContainer.someValue.value directly.
return Object.fromEntries(
Object.entries(this.injectedPublishContainer).map(([key, value]) => [
key,
isRef(value) ? value.value : value,
])
);
//
// We build the cache once with lazy getters, so the computed has zero reactive deps
// and is never invalidated. Dep tracking happens in the consumer's reactive scope.
if (this._publishContainerCache) return this._publishContainerCache;
const cache = {};
const src = this.injectedPublishContainer;
for (const key in src) {
const val = src[key];
if (isRef(val)) {
Object.defineProperty(cache, key, {
enumerable: true,
configurable: true,
get: () => val.value,
});
} else {
Object.defineProperty(cache, key, {
enumerable: true,
configurable: true,
writable: false,
value: val,
});
}
}
this._publishContainerCache = cache;
return cache;
},

name() {
Expand Down
14 changes: 11 additions & 3 deletions resources/js/components/fieldtypes/LinkFieldtype.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
<script>
import Fieldtype from './Fieldtype.vue';
import { Input, Select } from '@/components/ui';
import debounce from '@/util/debounce.js';
import { markRaw } from 'vue';

export default {
components: { Input, Text, Select },
Expand All @@ -60,6 +62,13 @@ export default {
};
},

created() {
this.syncUrlDebounced = markRaw(debounce((url) => {
this.update(url);
this.updateMeta({ ...this.meta, initialUrl: url });
}, 150));
},

computed: {
entryValue() {
return this.selectedEntries.length ? `entry::${this.selectedEntries[0]}` : null;
Expand Down Expand Up @@ -116,12 +125,11 @@ export default {

urlValue(url) {
if (this.metaChanging) return;

this.update(url);
this.updateMeta({ ...this.meta, initialUrl: url });
this.syncUrlDebounced(url);
},

meta(meta, oldMeta) {
if (meta === oldMeta) return;
if (JSON.stringify(meta) === JSON.stringify(oldMeta)) return;

this.metaChanging = true;
Expand Down
2 changes: 1 addition & 1 deletion resources/js/components/fieldtypes/TextFieldtype.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const shouldFocus = computed(() => {
if (props.config.focus === false || props.config.focus === true) {
return props.config.focus;
}

const isRootField = !props.fieldPathPrefix;
const isImplicitAutofocusField = name.value === 'title' || name.value === 'alt';

Expand Down
59 changes: 23 additions & 36 deletions resources/js/components/fieldtypes/bard/BardFieldtype.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<div :class="fullScreenMode && wrapperClasses">
<div
class="bard-fieldtype antialiased with-contrast:border-gray-500 shadow-ui-sm"
:class="{ 'bard-fullscreen': fullScreenMode }"
:class="{ 'bard-fullscreen': fullScreenMode, 'bard-bulk-op': suppressTransitions }"
ref="container"
@dragstart.stop="ignorePageHeader(true)"
@dragend="ignorePageHeader(false)"
Expand Down Expand Up @@ -177,6 +177,8 @@ import 'highlight.js/styles/github.css';
import importTiptap from '@/util/tiptap.js';
import { computed } from 'vue';
import { data_get } from "@/bootstrap/globals.js";
import extractBardText from "@/util/extractBardText";
import { createMountScheduler } from "@/util/createMountScheduler.js";

const lowlight = createLowlight(common);
let tiptap = null;
Expand Down Expand Up @@ -213,10 +215,12 @@ export default {
escBinding: null,
showAddSetButton: false,
hasBeenFocused: false,
suppressTransitions: false,
provide: {
bard: this.makeBardProvide(),
bardSets: this.config.sets,
showReplicatorFieldPreviews: this.config.previews,
mountScheduler: createMountScheduler(),
},
errorsById: {},
debounceNextUpdate: true,
Expand Down Expand Up @@ -294,25 +298,7 @@ export default {

replicatorPreview() {
if (!this.showFieldPreviews) return;
const stack = [...this.value];
let text = '';
while (stack.length) {
const node = stack.shift();
if (node.type === 'text') {
text += ` ${node.text || ''}`;
} else if (node.type === 'set') {
const handle = node.attrs.values.type;
const set = this.setConfigs.find((set) => set.handle === handle);
text += ` [${__(set ? set.display : handle)}]`;
}
if (text.length > 150) {
break;
}
if (node.content) {
stack.unshift(...node.content);
}
}
return text;
return extractBardText(this.value, 150, this.setConfigs);
},

inputIsInline() {
Expand Down Expand Up @@ -391,6 +377,7 @@ export default {

this.json = this.editor.getJSON().content;
this.html = this.editor.getHTML();
this._lastDocSize = this.editor.state.doc.content.size;

this.$nextTick(() => this.mounted = true);

Expand Down Expand Up @@ -643,11 +630,19 @@ export default {
},

collapseAll() {
this.suppressTransitions = true;
this.collapsed = Object.keys(this.meta.existing);
this.$nextTick(() => requestAnimationFrame(() => {
this.suppressTransitions = false;
}));
},

expandAll() {
this.suppressTransitions = true;
this.collapsed = [];
this.$nextTick(() => requestAnimationFrame(() => {
this.suppressTransitions = false;
}));
},

toggleCollapseSets() {
Expand Down Expand Up @@ -868,24 +863,16 @@ export default {
}
}, 1);
},
onUpdate: () => {
const oldJson = this.json;
const newJson = clone(this.editor.getJSON().content);

const countNodes = (nodes) => {
if (!nodes || !Array.isArray(nodes)) return 0;
let count = nodes.length;
nodes.forEach(node => {
if (node.content) {
count += countNodes(node.content);
}
});
return count;
};
onUpdate: ({ transaction }) => {
if (!transaction.docChanged) return;

const newDocSize = this.editor.state.doc.content.size;
const oldDocSize = this._lastDocSize ?? newDocSize;

if (countNodes(oldJson) !== countNodes(newJson)) this.debounceNextUpdate = false;
if (oldDocSize !== newDocSize) this.debounceNextUpdate = false;
this._lastDocSize = newDocSize;

this.json = newJson;
this.json = this.editor.getJSON().content;
this.html = this.editor.getHTML();
},
onCreate: ({ editor }) => {
Expand Down
Loading
Loading