@panphora/hyper-cms 0.11.5 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -6
- package/dist/hypercms.min.js +169 -84
- package/package.json +5 -3
- package/src/apply-loop.js +3 -2
- package/src/catalogs/colors.js +293 -0
- package/src/catalogs/fonts.js +126 -0
- package/src/catalogs/index.js +3 -0
- package/src/catalogs/variant-icons.js +24 -0
- package/src/color-control.js +196 -0
- package/src/events.js +25 -2
- package/src/font-control.js +142 -0
- package/src/fonts-link.js +83 -0
- package/src/form-builder.js +85 -3
- package/src/form-rules.js +48 -3
- package/src/hypercms.js +111 -21
- package/src/page-root.js +28 -0
- package/src/refresh.js +4 -1
- package/src/session.js +51 -3
- package/src/targets.js +55 -13
- package/src/templates.js +100 -6
- package/src/theme/pixel-quiet.overrides.css +91 -0
- package/src/theme.generated.css +91 -0
- package/src/toggle.js +80 -296
- package/src/variant-control.js +46 -0
- package/src/views/inline-layer.js +71 -15
- package/src/views/inline.js +87 -17
|
@@ -40,7 +40,7 @@ function hosts(row, strip) {
|
|
|
40
40
|
return strip.width <= row.width && strip.height <= row.height
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
43
|
+
export function createInlineLayer({ doc, layerEl, onActivate, onListAction, onStyle }) {
|
|
44
44
|
const win = doc.defaultView
|
|
45
45
|
// Every positioned thing the layer draws, whatever kind: a handle, a row
|
|
46
46
|
// strip, a list's Add. One array, because all three are placed by one pass.
|
|
@@ -135,6 +135,14 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
135
135
|
spot.node.hidden = true
|
|
136
136
|
continue
|
|
137
137
|
}
|
|
138
|
+
// A Style chip sits inside its element's top-left corner, clear of the
|
|
139
|
+
// row strips and handles that take the top-right.
|
|
140
|
+
if (spot.kind === 'style') {
|
|
141
|
+
const x = Math.max(8, Math.min(anchor.left, viewport.width - handle.width - 8))
|
|
142
|
+
const y = Math.max(8, Math.min(anchor.top, viewport.height - handle.height - 8))
|
|
143
|
+
spot.node.style.transform = `translate(${Math.round(x)}px, ${Math.round(y)}px)`
|
|
144
|
+
continue
|
|
145
|
+
}
|
|
138
146
|
const prefer = spot.kind === 'handle' ? null : CONTROL_PLACEMENT
|
|
139
147
|
let { x, y } = placeHandle({ anchor, handle, viewport, ...prefer })
|
|
140
148
|
const pencil = spot.members.find((member) => member.kind === 'handle')
|
|
@@ -272,6 +280,7 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
272
280
|
|
|
273
281
|
function sameMember(member, spec) {
|
|
274
282
|
if (member.kind !== spec.kind) return false
|
|
283
|
+
if (member.kind === 'style') return true
|
|
275
284
|
if (member.kind === 'handle') return targetIdentity(member.target) === targetIdentity(spec.target)
|
|
276
285
|
if (member.kind === 'row') return member.row === spec.row && sameList(member.list, spec.list)
|
|
277
286
|
return sameList(member.list, spec.list)
|
|
@@ -301,6 +310,21 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
301
310
|
return member
|
|
302
311
|
}
|
|
303
312
|
|
|
313
|
+
function makeStyleChip(spec) {
|
|
314
|
+
const button = doc.createElement('button')
|
|
315
|
+
button.type = 'button'
|
|
316
|
+
button.className = 'hcms-inline-style-chip mirk-button mirk-button--small'
|
|
317
|
+
button.setAttribute('aria-label', 'Edit style')
|
|
318
|
+
button.innerHTML = '<span class="mirk-button__label">Style</span>'
|
|
319
|
+
const member = { node: button, kind: 'style', group: spec.group }
|
|
320
|
+
button.addEventListener('click', (event) => {
|
|
321
|
+
event.preventDefault()
|
|
322
|
+
event.stopPropagation()
|
|
323
|
+
onStyle?.(member.group, button)
|
|
324
|
+
})
|
|
325
|
+
return member
|
|
326
|
+
}
|
|
327
|
+
|
|
304
328
|
function makeListButton(action, label) {
|
|
305
329
|
const button = doc.createElement('button')
|
|
306
330
|
button.type = 'button'
|
|
@@ -380,15 +404,23 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
380
404
|
} else if (event.key === 'Tab') closeSettings(true)
|
|
381
405
|
else if (['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key) && openSettings.menu.contains(event.target)) {
|
|
382
406
|
event.preventDefault()
|
|
383
|
-
openSettings.menu.
|
|
407
|
+
const items = [...openSettings.menu.querySelectorAll('[role="menuitem"]')]
|
|
408
|
+
const at = items.indexOf(event.target)
|
|
409
|
+
const next = event.key === 'Home' ? 0
|
|
410
|
+
: event.key === 'End' ? items.length - 1
|
|
411
|
+
: at === -1 ? 0
|
|
412
|
+
: (at + (event.key === 'ArrowDown' ? 1 : -1) + items.length) % items.length
|
|
413
|
+
items[next]?.focus({ preventScroll: true })
|
|
384
414
|
}
|
|
385
415
|
}
|
|
386
416
|
|
|
387
|
-
function updateSettings(member, { list, row, rowIndex }) {
|
|
388
|
-
Object.assign(member, { list, row, index: rowIndex })
|
|
417
|
+
function updateSettings(member, { list, row, rowIndex, style = null }) {
|
|
418
|
+
Object.assign(member, { list, row, index: rowIndex, style })
|
|
389
419
|
member.node.setAttribute('data-hcms-list', list.path.join('.'))
|
|
390
420
|
member.node.setAttribute('data-hcms-row', String(rowIndex))
|
|
391
421
|
member.button.setAttribute('aria-label', `Settings ${list.path.join('.')}.${rowIndex}`)
|
|
422
|
+
if (style && !member.styleItem.isConnected) member.menu.insertBefore(member.styleItem, member.menu.firstChild)
|
|
423
|
+
else if (!style) member.styleItem.remove()
|
|
392
424
|
}
|
|
393
425
|
|
|
394
426
|
function makeSettings(spec) {
|
|
@@ -402,6 +434,11 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
402
434
|
menu.setAttribute('role', 'menu')
|
|
403
435
|
menu.setAttribute('aria-label', 'Item settings')
|
|
404
436
|
menu.hidden = true
|
|
437
|
+
const styleItem = doc.createElement('button')
|
|
438
|
+
styleItem.type = 'button'
|
|
439
|
+
styleItem.setAttribute('role', 'menuitem')
|
|
440
|
+
styleItem.setAttribute('data-hcms-style-action', '')
|
|
441
|
+
styleItem.textContent = 'Style'
|
|
405
442
|
const remove = doc.createElement('button')
|
|
406
443
|
remove.type = 'button'
|
|
407
444
|
remove.setAttribute('role', 'menuitem')
|
|
@@ -409,7 +446,7 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
409
446
|
remove.textContent = 'Delete'
|
|
410
447
|
menu.appendChild(remove)
|
|
411
448
|
node.append(button, menu)
|
|
412
|
-
const member = { node, button, menu, kind: 'settings' }
|
|
449
|
+
const member = { node, button, menu, styleItem, kind: 'settings' }
|
|
413
450
|
updateSettings(member, spec)
|
|
414
451
|
const show = () => {
|
|
415
452
|
closeSettings()
|
|
@@ -417,7 +454,7 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
417
454
|
menu.hidden = false
|
|
418
455
|
button.setAttribute('aria-expanded', 'true')
|
|
419
456
|
node.parentElement.classList.add('has-open-settings')
|
|
420
|
-
|
|
457
|
+
menu.querySelector('[role="menuitem"]').focus({ preventScroll: true })
|
|
421
458
|
schedule()
|
|
422
459
|
}
|
|
423
460
|
button.addEventListener('click', (event) => {
|
|
@@ -438,6 +475,12 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
438
475
|
closeSettings(true)
|
|
439
476
|
onListAction?.({ action: 'remove', list: member.list, index: member.index, row: member.row })
|
|
440
477
|
})
|
|
478
|
+
styleItem.addEventListener('click', (event) => {
|
|
479
|
+
event.preventDefault()
|
|
480
|
+
event.stopPropagation()
|
|
481
|
+
closeSettings()
|
|
482
|
+
onStyle?.(member.style, member.button)
|
|
483
|
+
})
|
|
441
484
|
return member
|
|
442
485
|
}
|
|
443
486
|
|
|
@@ -445,6 +488,7 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
445
488
|
if (member.kind === 'handle') updateHandle(member, spec.target)
|
|
446
489
|
else if (member.kind === 'row') updateRowControls(member, spec)
|
|
447
490
|
else if (member.kind === 'settings') updateSettings(member, spec)
|
|
491
|
+
else if (member.kind === 'style') member.group = spec.group
|
|
448
492
|
}
|
|
449
493
|
|
|
450
494
|
function addDesired(desired, desiredIndex, el, spec, category) {
|
|
@@ -459,7 +503,7 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
459
503
|
spot.members.push(spec)
|
|
460
504
|
}
|
|
461
505
|
|
|
462
|
-
function addListControls(desired, desiredIndex, list) {
|
|
506
|
+
function addListControls(desired, desiredIndex, list, rowStyles) {
|
|
463
507
|
const rows = list.items || []
|
|
464
508
|
rows.forEach((el, i) => {
|
|
465
509
|
if (!isAnchorable(el)) return
|
|
@@ -467,7 +511,7 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
467
511
|
kind: 'row', list, row: el, rowIndex: i, count: rows.length,
|
|
468
512
|
}, 'item')
|
|
469
513
|
addDesired(desired, desiredIndex, el, {
|
|
470
|
-
kind: 'settings', list, row: el, rowIndex: i,
|
|
514
|
+
kind: 'settings', list, row: el, rowIndex: i, style: rowStyles.get(el) || null,
|
|
471
515
|
}, 'item')
|
|
472
516
|
})
|
|
473
517
|
}
|
|
@@ -481,7 +525,9 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
481
525
|
? makeHandle(spec.target)
|
|
482
526
|
: spec.kind === 'row'
|
|
483
527
|
? makeRowControls(spec.list, spec.row, spec.rowIndex, spec.count)
|
|
484
|
-
:
|
|
528
|
+
: spec.kind === 'style'
|
|
529
|
+
? makeStyleChip(spec)
|
|
530
|
+
: makeSettings(spec))
|
|
485
531
|
unused.delete(member)
|
|
486
532
|
updateMember(member, spec)
|
|
487
533
|
if (controlsHidden && member.kind !== 'handle') member.node.hidden = true
|
|
@@ -498,18 +544,26 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
498
544
|
spot.members = next
|
|
499
545
|
}
|
|
500
546
|
|
|
501
|
-
function reconcile(targetList, lists) {
|
|
547
|
+
function reconcile(targetList, lists, groups) {
|
|
502
548
|
const desired = []
|
|
503
549
|
const desiredIndex = new Map()
|
|
504
550
|
const nextTargets = new Map()
|
|
505
551
|
let nextHandleCount = 0
|
|
506
552
|
for (const target of targetList || []) {
|
|
553
|
+
if (target.style) continue
|
|
507
554
|
if (!nextTargets.has(target.el)) nextTargets.set(target.el, target)
|
|
508
555
|
if (target.kind !== 'handle' || !isAnchorable(target.el)) continue
|
|
509
556
|
addDesired(desired, desiredIndex, target.el, { kind: 'handle', target }, 'item')
|
|
510
557
|
nextHandleCount++
|
|
511
558
|
}
|
|
512
|
-
|
|
559
|
+
const rowStyles = new Map()
|
|
560
|
+
for (const group of groups || []) {
|
|
561
|
+
if (group.scope === 'row') rowStyles.set(group.el, group)
|
|
562
|
+
else if (group.scope === 'section' && isAnchorable(group.el)) {
|
|
563
|
+
addDesired(desired, desiredIndex, group.el, { kind: 'style', group }, 'style')
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
for (const list of lists || []) addListControls(desired, desiredIndex, list, rowStyles)
|
|
513
567
|
|
|
514
568
|
const unused = new Set(placements)
|
|
515
569
|
const visibility = new Map()
|
|
@@ -540,8 +594,10 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
540
594
|
reconcileMembers(spot, wanted.members)
|
|
541
595
|
spot.kind = spot.members.some((member) => member.kind === 'row')
|
|
542
596
|
? 'row'
|
|
543
|
-
: spot.members.some((member) => member.kind === 'handle')
|
|
544
|
-
|
|
597
|
+
: spot.members.some((member) => member.kind === 'handle')
|
|
598
|
+
? 'handle'
|
|
599
|
+
: spot.members.some((member) => member.kind === 'style') ? 'style' : 'add'
|
|
600
|
+
spot.node.setAttribute('aria-label', spot.category === 'add' ? 'List controls' : spot.category === 'style' ? 'Style controls' : 'Item controls')
|
|
545
601
|
next.push(spot)
|
|
546
602
|
}
|
|
547
603
|
for (const spot of unused) spot.node.remove()
|
|
@@ -580,8 +636,8 @@ export function createInlineLayer({ doc, layerEl, onActivate, onListAction }) {
|
|
|
580
636
|
}
|
|
581
637
|
|
|
582
638
|
return {
|
|
583
|
-
setTargets(list, lists) {
|
|
584
|
-
reconcile(list, lists)
|
|
639
|
+
setTargets(list, lists, groups = []) {
|
|
640
|
+
reconcile(list, lists, groups)
|
|
585
641
|
ghosts.setLists(lists)
|
|
586
642
|
syncObservation()
|
|
587
643
|
listen()
|
package/src/views/inline.js
CHANGED
|
@@ -36,7 +36,7 @@ import { applyUnresolvedState } from '../unresolved.js'
|
|
|
36
36
|
import { refreshForm } from '../refresh.js'
|
|
37
37
|
import { clearSessionOpen, markSessionOpen, reensureStyles } from '../shell.js'
|
|
38
38
|
import { isAnchorable } from '../anchor.js'
|
|
39
|
-
import { resolveTargets } from '../targets.js'
|
|
39
|
+
import { resolveTargets, styleGroups } from '../targets.js'
|
|
40
40
|
import { createContentView } from '../lib/content-dom.js'
|
|
41
41
|
import { morph } from 'hyper-morph'
|
|
42
42
|
import { place } from '../place.js'
|
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
import { installSnapshotHook } from '../hooks.js'
|
|
55
55
|
import { createInlineLayer } from './inline-layer.js'
|
|
56
56
|
import { inlineIcon } from '../inline-icons.js'
|
|
57
|
+
import { contentRoot } from '../page-root.js'
|
|
57
58
|
|
|
58
59
|
const HOST_TAG = 'hypercms-inline'
|
|
59
60
|
|
|
@@ -89,6 +90,7 @@ export function createInlineView({ doc, pageRoot, opts = {} }) {
|
|
|
89
90
|
// the first placement toward wherever the last field happened to sit.
|
|
90
91
|
let activeTarget = null
|
|
91
92
|
let activeHandle = null
|
|
93
|
+
let groupsNow = []
|
|
92
94
|
let popMode = null
|
|
93
95
|
|
|
94
96
|
// Build one binding: the editor, the marker, the snapshot hook, and the two
|
|
@@ -258,6 +260,7 @@ export function createInlineView({ doc, pageRoot, opts = {} }) {
|
|
|
258
260
|
// The handle and the page click are two doors to one room.
|
|
259
261
|
onActivate: (target, handle) => this.activate(target, handle),
|
|
260
262
|
onListAction: (op) => this.listAction(op),
|
|
263
|
+
onStyle: (group, handle) => this.openStyle(group, handle),
|
|
261
264
|
})
|
|
262
265
|
layer.setFollower(() => this.placePopover())
|
|
263
266
|
host.closeEl.addEventListener('click', () => this.deactivate())
|
|
@@ -266,6 +269,12 @@ export function createInlineView({ doc, pageRoot, opts = {} }) {
|
|
|
266
269
|
event.stopPropagation()
|
|
267
270
|
this.toggleControls()
|
|
268
271
|
})
|
|
272
|
+
host.pageStyleEl.addEventListener('click', (event) => {
|
|
273
|
+
event.preventDefault()
|
|
274
|
+
event.stopPropagation()
|
|
275
|
+
const group = groupsNow.find((candidate) => candidate.scope === 'page')
|
|
276
|
+
if (group) this.openStyle(group, host.pageStyleEl)
|
|
277
|
+
})
|
|
269
278
|
// There is no drawer. What a field with no visual representation gets is
|
|
270
279
|
// this one tap out to the view that edits everything.
|
|
271
280
|
// The switch carries the session's options across (hypercms.js open()), so
|
|
@@ -339,7 +348,7 @@ export function createInlineView({ doc, pageRoot, opts = {} }) {
|
|
|
339
348
|
// per target: the target set is rebuilt on every refresh, and per-element
|
|
340
349
|
// listeners would have to be torn down and reattached with it.
|
|
341
350
|
bindPage() {
|
|
342
|
-
const root = this.ctx.pageRoot
|
|
351
|
+
const root = contentRoot(this.ctx.pageRoot)
|
|
343
352
|
const hostRoot = host.root
|
|
344
353
|
|
|
345
354
|
const onPointerOver = (event) => {
|
|
@@ -405,7 +414,7 @@ export function createInlineView({ doc, pageRoot, opts = {} }) {
|
|
|
405
414
|
// carries it for.
|
|
406
415
|
const onChanged = (event) => {
|
|
407
416
|
const detail = event.detail
|
|
408
|
-
if (!detail || detail.pageRoot !== this.ctx.pageRoot || !detail.path) return
|
|
417
|
+
if (!detail || detail.pageRoot !== contentRoot(this.ctx.pageRoot) || !detail.path) return
|
|
409
418
|
for (const binding of bindings.values()) {
|
|
410
419
|
if (binding.path === detail.path) binding.written = true
|
|
411
420
|
}
|
|
@@ -448,6 +457,7 @@ export function createInlineView({ doc, pageRoot, opts = {} }) {
|
|
|
448
457
|
activeTarget = target
|
|
449
458
|
activeHandle = handle || null
|
|
450
459
|
popMode = null
|
|
460
|
+
host.popTitleEl.textContent = 'Edit content'
|
|
451
461
|
|
|
452
462
|
// Unhide BEFORE measuring. A hidden popover has a zero rect, which places
|
|
453
463
|
// it at the clamp instead of beside its anchor — the same trap as the 0px
|
|
@@ -458,6 +468,33 @@ export function createInlineView({ doc, pageRoot, opts = {} }) {
|
|
|
458
468
|
focusFirst(leaf)
|
|
459
469
|
},
|
|
460
470
|
|
|
471
|
+
// A style popover shows exactly one group's style fields: the page's from
|
|
472
|
+
// the bar, a section's from its chip, a row's from its gear menu. The
|
|
473
|
+
// section and row ones sit beside what they style; the page one beside the
|
|
474
|
+
// button, because the whole page is no place to anchor a popover.
|
|
475
|
+
openStyle(group, handle) {
|
|
476
|
+
if (!group || !host) return
|
|
477
|
+
const leaf = revealPaths(this, host, group.paths)
|
|
478
|
+
if (!leaf) {
|
|
479
|
+
this.deactivate()
|
|
480
|
+
return
|
|
481
|
+
}
|
|
482
|
+
activeTarget = {
|
|
483
|
+
kind: 'style',
|
|
484
|
+
scope: group.scope,
|
|
485
|
+
el: group.scope === 'page' ? host.pageStyleEl : group.el,
|
|
486
|
+
path: group.paths[0].split('.'),
|
|
487
|
+
paths: group.paths,
|
|
488
|
+
}
|
|
489
|
+
activeHandle = handle || null
|
|
490
|
+
popMode = null
|
|
491
|
+
host.popTitleEl.textContent = group.scope === 'page' ? 'Page style' : 'Style'
|
|
492
|
+
host.popEl.hidden = false
|
|
493
|
+
host.formRoot.querySelectorAll(`.${ACTIVE_CLASS}`).forEach(autosizeIn)
|
|
494
|
+
this.placePopover()
|
|
495
|
+
focusFirst(leaf)
|
|
496
|
+
},
|
|
497
|
+
|
|
461
498
|
// Bind richclay to the page element and edit the text where it sits.
|
|
462
499
|
// Returns false when the target cannot be bound, which is the caller's
|
|
463
500
|
// signal to open the popover over it instead.
|
|
@@ -511,13 +548,23 @@ export function createInlineView({ doc, pageRoot, opts = {} }) {
|
|
|
511
548
|
syncTargets() {
|
|
512
549
|
if (!layer) return
|
|
513
550
|
const ctx = this.ctx
|
|
514
|
-
const
|
|
515
|
-
|
|
551
|
+
const resolved = resolveTargets(ctx.pageRoot, ctx.pageRules, doc)
|
|
552
|
+
const lists = resolved.lists
|
|
553
|
+
const targets = resolved.targets.filter((target) => !target.style)
|
|
554
|
+
groupsNow = styleGroups(resolved.targets, lists)
|
|
555
|
+
host.pageStyleEl.hidden = !groupsNow.some((group) => group.scope === 'page')
|
|
556
|
+
layer.setTargets(resolved.targets, lists, groupsNow)
|
|
516
557
|
const byEl = reconcileBindings(this, bindings, targets, doc)
|
|
517
558
|
// An open popover holds its path the same way a binding does. Re-point it
|
|
518
559
|
// at the target that now stands for the element it is anchored over, or
|
|
519
560
|
// the popover keeps editing the row that inherited its old index.
|
|
520
|
-
if (activeTarget) {
|
|
561
|
+
if (activeTarget?.kind === 'style') {
|
|
562
|
+
const group = activeTarget.scope === 'page'
|
|
563
|
+
? groupsNow.find((candidate) => candidate.scope === 'page')
|
|
564
|
+
: groupsNow.find((candidate) => candidate.el === activeTarget.el)
|
|
565
|
+
if (group) activeTarget = { ...activeTarget, paths: group.paths, path: group.paths[0].split('.') }
|
|
566
|
+
else this.deactivate()
|
|
567
|
+
} else if (activeTarget) {
|
|
521
568
|
const candidates = byEl.get(activeTarget.el) || []
|
|
522
569
|
const fresh = candidates.find((target) => sameTargetBinding(target, activeTarget)) ||
|
|
523
570
|
candidates.find((target) => target.path.join('.') === activeTarget.path.join('.')) ||
|
|
@@ -644,7 +691,9 @@ export function createInlineView({ doc, pageRoot, opts = {} }) {
|
|
|
644
691
|
this.deactivate()
|
|
645
692
|
return
|
|
646
693
|
}
|
|
647
|
-
const leaf =
|
|
694
|
+
const leaf = activeTarget.kind === 'style'
|
|
695
|
+
? revealPaths(this, host, activeTarget.paths)
|
|
696
|
+
: revealPath(this, host, activeTarget.path.join('.'))
|
|
648
697
|
if (!leaf) {
|
|
649
698
|
this.deactivate()
|
|
650
699
|
return
|
|
@@ -951,18 +1000,34 @@ function revealPath(view, host, path) {
|
|
|
951
1000
|
field.closest('[data-hcms-shape="object-array"], [data-hcms-shape="scalar-array"]') === item.parentElement.closest('[data-hcms-shape="object-array"]'))
|
|
952
1001
|
: [leaf]
|
|
953
1002
|
if (!fields.includes(leaf)) fields.push(leaf)
|
|
954
|
-
for (const field of fields)
|
|
955
|
-
field.classList.add(ACTIVE_CLASS)
|
|
956
|
-
field.removeAttribute('draggable')
|
|
957
|
-
for (let el = field.parentElement; el; el = el.parentElement) {
|
|
958
|
-
el.classList.add(ONPATH_CLASS)
|
|
959
|
-
el.removeAttribute('draggable')
|
|
960
|
-
if (el === view.formRoot) break
|
|
961
|
-
}
|
|
962
|
-
}
|
|
1003
|
+
for (const field of fields) markRevealed(view, field)
|
|
963
1004
|
return leaf
|
|
964
1005
|
}
|
|
965
1006
|
|
|
1007
|
+
// Reveal exactly these fields, with no card siblings: a style popover shows
|
|
1008
|
+
// style fields only.
|
|
1009
|
+
function revealPaths(view, host, paths) {
|
|
1010
|
+
clearPathClasses(host.root)
|
|
1011
|
+
let first = null
|
|
1012
|
+
for (const path of paths) {
|
|
1013
|
+
const field = view.formRoot && view.formRoot.querySelector(`[data-hcms-path="${cssEscape(path)}"]`)
|
|
1014
|
+
if (!field) continue
|
|
1015
|
+
first = first || field
|
|
1016
|
+
markRevealed(view, field)
|
|
1017
|
+
}
|
|
1018
|
+
return first
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
function markRevealed(view, field) {
|
|
1022
|
+
field.classList.add(ACTIVE_CLASS)
|
|
1023
|
+
field.removeAttribute('draggable')
|
|
1024
|
+
for (let el = field.parentElement; el; el = el.parentElement) {
|
|
1025
|
+
el.classList.add(ONPATH_CLASS)
|
|
1026
|
+
el.removeAttribute('draggable')
|
|
1027
|
+
if (el === view.formRoot) break
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
|
|
966
1031
|
function clearPathClasses(root) {
|
|
967
1032
|
if (!root) return
|
|
968
1033
|
for (const el of root.querySelectorAll(`.${ACTIVE_CLASS}, .${ONPATH_CLASS}`)) {
|
|
@@ -1036,6 +1101,9 @@ function mountInlineHost(doc, theme) {
|
|
|
1036
1101
|
<span class="mirk-button__label">Edit in the sidebar</span>
|
|
1037
1102
|
</button>
|
|
1038
1103
|
</div>
|
|
1104
|
+
<button type="button" class="hcms-inline-page-style mirk-button mirk-button--small" data-hcms-page-style-open hidden>
|
|
1105
|
+
<span class="mirk-button__label">Page style</span>
|
|
1106
|
+
</button>
|
|
1039
1107
|
<button type="button" class="hcms-inline-toggle mirk-button mirk-button--small" data-hcms-controls-toggle aria-pressed="false" hidden>
|
|
1040
1108
|
<span class="mirk-button__label">Hide controls</span>
|
|
1041
1109
|
</button>
|
|
@@ -1045,7 +1113,7 @@ function mountInlineHost(doc, theme) {
|
|
|
1045
1113
|
<div class="hcms-inline-layer"></div>
|
|
1046
1114
|
<div class="hcms-inline-pop" role="dialog" aria-label="Edit content" hidden>
|
|
1047
1115
|
<div class="hcms-inline-pop-header">
|
|
1048
|
-
<span>Edit content</span>
|
|
1116
|
+
<span class="hcms-inline-pop-title">Edit content</span>
|
|
1049
1117
|
<button type="button" class="hcms-inline-pop-close mirk-button mirk-button--small" aria-label="Close field editor">
|
|
1050
1118
|
<span class="mirk-button__label">${inlineIcon('remove')}</span>
|
|
1051
1119
|
</button>
|
|
@@ -1067,6 +1135,8 @@ function mountInlineHost(doc, theme) {
|
|
|
1067
1135
|
popEl: root.querySelector('.hcms-inline-pop'),
|
|
1068
1136
|
closeEl: root.querySelector('.hcms-inline-pop-close'),
|
|
1069
1137
|
toggleEl: root.querySelector('[data-hcms-controls-toggle]'),
|
|
1138
|
+
pageStyleEl: root.querySelector('[data-hcms-page-style-open]'),
|
|
1139
|
+
popTitleEl: root.querySelector('.hcms-inline-pop-title'),
|
|
1070
1140
|
destroy() { root.remove() },
|
|
1071
1141
|
}
|
|
1072
1142
|
}
|