domma-cms 1.10.38 → 1.11.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.
@@ -19,7 +19,7 @@ import {contentsOverrideFromAttrs} from './pageContents.js';
19
19
  import {buildMenuNav} from './menuRender.js';
20
20
  import {checkVisibility} from '../middleware/auth.js';
21
21
  import {getRoleHierarchy, getRoleLevel} from './roles.js';
22
- import {buildTextStyle} from '../../public/js/text-style.mjs';
22
+ import {buildTextStyle, buildTextMotion} from '../../public/js/text-style.mjs';
23
23
  import {buildScribeStyle} from '../../public/js/scribe-style.mjs';
24
24
  import {CHARACTERS, resolveCharacterSize} from '../../public/js/celebrations/character-catalog.mjs';
25
25
  import {publicButtonSettings} from '../../public/js/form-submit.mjs';
@@ -2348,7 +2348,10 @@ function processGridBlocks(markdown) {
2348
2348
  const revealStagger = attrs['reveal-stagger'] ? ` data-reveal-stagger="${escapeAttr(attrs['reveal-stagger'])}"` : '';
2349
2349
  const revealDelay = attrs['reveal-delay'] ? ` data-reveal-delay="${escapeAttr(attrs['reveal-delay'])}"` : '';
2350
2350
  const revealDirection = attrs['reveal-direction'] ? ` data-reveal-direction="${escapeAttr(attrs['reveal-direction'])}"` : '';
2351
- return `<div class="${classes.join(' ')}"${id}${reveal}${revealMode}${revealAnimation}${revealDuration}${revealStagger}${revealDelay}${revealDirection}>${inner}</div>\n`;
2351
+ // Swoosh in again each time the row comes back up into view; cards that lean toward the pointer.
2352
+ const revealReplay = isTruthyAttr(attrs['reveal-replay']) ? ' data-reveal-replay="true"' : '';
2353
+ const tilt = isTruthyAttr(attrs.tilt) ? ' data-tilt="true"' : '';
2354
+ return `<div class="${classes.join(' ')}"${id}${reveal}${revealMode}${revealAnimation}${revealDuration}${revealStagger}${revealDelay}${revealDirection}${revealReplay}${tilt}>${inner}</div>\n`;
2352
2355
  }
2353
2356
  );
2354
2357
 
@@ -3690,19 +3693,27 @@ function processTextBlocks(markdown) {
3690
3693
  const attrs = parseShortcodeAttrs(attrStr || '');
3691
3694
  // The attribute → CSS mapping is shared with the admin editor's live
3692
3695
  // preview (public/js/text-style.mjs), so the two cannot disagree.
3693
- const style = buildTextStyle(attrs);
3696
+ // Gradient, shine, light-up and word-by-word (text-motion.mjs moves them).
3697
+ const motion = buildTextMotion(attrs);
3698
+ const style = [buildTextStyle(attrs), motion.style].filter(Boolean).join(';');
3694
3699
  const styleAttr = style ? ` style="${style}"` : '';
3695
- const classAttr = attrs.class ? ` class="${escapeAttr(attrs.class)}"` : '';
3700
+ const classes = [...motion.classes, ...(attrs.class ? [attrs.class] : [])].join(' ');
3701
+ const classAttr = classes ? ` class="${escapeAttr(classes)}"` : '';
3696
3702
  const idAttr = attrs.id ? ` id="${escapeAttr(attrs.id)}"` : '';
3697
3703
 
3698
3704
  return `<span${styleAttr}${classAttr}${idAttr}>${inner.trim()}</span>`;
3699
3705
  }
3700
3706
 
3701
- // Note: [\s\S]*? allows multi-line body content (deliberate divergence from badge's [^\n]*?)
3702
- const result = scrubbed.replace(
3703
- /\[text([^\]]*)\]([\s\S]*?)\[\/text\]/gi,
3704
- (_, attrStr, body) => buildText(attrStr, body)
3705
- );
3707
+ // Note: [\s\S]*? allows multi-line body content (deliberate divergence from badge's [^\n]*?).
3708
+ // Innermost first, round again until none is left, so a [text] can sit inside another -
3709
+ // a gradient phrase inside a headline that rises word by word.
3710
+ const INNERMOST = /\[text(\s[^\]]*)?\]((?:(?!\[text[\s\]])[\s\S])*?)\[\/text\]/gi;
3711
+ let result = scrubbed;
3712
+ for (let pass = 0; pass < 8; pass++) {
3713
+ const next = result.replace(INNERMOST, (_, attrStr, body) => buildText(attrStr, body));
3714
+ if (next === result) break;
3715
+ result = next;
3716
+ }
3706
3717
 
3707
3718
  return restore(result);
3708
3719
  }
@@ -3985,8 +3996,8 @@ function processSpacerBlocks(markdown) {
3985
3996
  * Any Behaviour setting of the menu, as attributes (see NAVBAR_OVERRIDE_ATTRS in
3986
3997
  * menus.js): position, orientation, side, align, variant, hover-open, hover,
3987
3998
  * selected, accent, class, font, font-size, font-weight, letter-spacing,
3988
- * icon-size, width, collapsible, collapsed, autohide, hide-on-scroll and the
3989
- * float-* panel options. `true` / `false` switch a setting on or off; an empty
3999
+ * icon-size, width, collapsible, collapsed, autohide, hide-on-scroll, bar, dropdown,
4000
+ * tiles, morph and the float-* panel options. `true` / `false` switch a setting on or off; an empty
3990
4001
  * value clears it. Leaves a hidden marker the renderer reads (the first tag on
3991
4002
  * a page counts) - it draws nothing itself.
3992
4003
  *
@@ -22,6 +22,9 @@ import {
22
22
  PRESET_COLOUR_VARS, PRESET_COLOUR_FALLBACKS, colourToCss, cssClassProblems
23
23
  } from '../../public/js/menu-decor.mjs';
24
24
  import {fileIn} from './safePath.js';
25
+ import {normaliseLook, lookProblems, itemLookProblems} from '../../public/js/menu-look.mjs';
26
+
27
+ export {normaliseLook};
25
28
 
26
29
  /**
27
30
  * Bust the response-cache tags that menu changes affect. Public pages are
@@ -312,6 +315,8 @@ export const NAVBAR_OVERRIDE_ATTRS = {
312
315
  'width': ['dock', 'width', 'num'], 'collapsible': ['dock', 'collapsible', 'bool'],
313
316
  'collapsed': ['dock', 'collapsed', 'bool'], 'autohide': ['dock', 'autohide', 'bool'],
314
317
  'hide-on-scroll': ['dock', 'hideOnScroll', 'bool'],
318
+ 'bar': ['look', 'bar'], 'dropdown': ['look', 'dropdown'], 'tiles': ['look', 'tiles'],
319
+ 'morph': ['look', 'morph', 'bool'],
315
320
  'float-anchor': ['float', 'anchor'], 'float-x': ['float', 'offsetX', 'num'], 'float-y': ['float', 'offsetY', 'num'],
316
321
  'float-width': ['float', 'width', 'num'], 'float-radius': ['float', 'radius', 'num'],
317
322
  'float-shadow': ['float', 'shadow'], 'float-accent': ['float', 'accent'], 'float-opacity': ['float', 'opacity', 'num'],
@@ -367,6 +372,10 @@ export function applyMenuOverride(menu, override) {
367
372
  const dock = normaliseDock(next.dock);
368
373
  if (dock) next.dock = dock; else delete next.dock;
369
374
  }
375
+ if (next.look) {
376
+ const look = normaliseLook(next.look);
377
+ if (look) next.look = look; else delete next.look;
378
+ }
370
379
  return next;
371
380
  }
372
381
 
@@ -620,6 +629,7 @@ export async function createMenu(input) {
620
629
  ...(input.style != null && {style: input.style}),
621
630
  ...(normaliseDock(input.dock) && {dock: normaliseDock(input.dock)}),
622
631
  ...(normaliseMobile(input.mobile) && {mobile: normaliseMobile(input.mobile)}),
632
+ ...(normaliseLook(input.look) && {look: normaliseLook(input.look)}),
623
633
  ...(binding != null && {binding}),
624
634
  items: Array.isArray(input.items) ? input.items : [],
625
635
  meta: {
@@ -669,6 +679,7 @@ export async function updateMenu(slug, input) {
669
679
  ...(input.style != null && {style: input.style}),
670
680
  ...(normaliseDock(input.dock) && {dock: normaliseDock(input.dock)}),
671
681
  ...(normaliseMobile(input.mobile) && {mobile: normaliseMobile(input.mobile)}),
682
+ ...(normaliseLook(input.look) && {look: normaliseLook(input.look)}),
672
683
  ...(binding != null && {binding}),
673
684
  items: Array.isArray(input.items) ? input.items : [],
674
685
  meta: {
@@ -886,6 +897,8 @@ export function validateMenu(menu) {
886
897
  }
887
898
  }
888
899
  }
900
+ // Bar shape and dropdown style - see public/js/menu-look.mjs.
901
+ errors.push(...lookProblems(menu.look));
889
902
  if (menu.highlight != null) {
890
903
  if (typeof menu.highlight !== 'object' || Array.isArray(menu.highlight)) {
891
904
  errors.push('highlight must be an object');
@@ -996,6 +1009,8 @@ export function validateMenu(menu) {
996
1009
  if (item.colour != null && !isValidColour(item.colour)) {
997
1010
  errors.push(`Item ${path}: colour must be a preset key or #rrggbb`);
998
1011
  }
1012
+ // Card dropdown fields (description, tile, chip, panel) - menu-look.mjs.
1013
+ for (const p of itemLookProblems(item, isValidColour)) errors.push(`Item ${path}: ${p}`);
999
1014
  for (const p of cssClassProblems(item.class)) errors.push(`Item ${path}: class: ${p}`);
1000
1015
  // Per-item highlight override. Same shape and same value sets as
1001
1016
  // the menu-level `highlight` block validated above - an item that
@@ -390,6 +390,8 @@ export async function renderPage(page, opts = {}) {
390
390
  // wires it; width and autohide also shape the body below, from the first paint.
391
391
  ...(navMenu.dock && {dock: navMenu.dock}),
392
392
  ...(navMenu.mobile && {mobile: navMenu.mobile}),
393
+ // Bar shape and card dropdowns - drawn by menu-cards.mjs in the browser.
394
+ ...(navMenu.look && {look: navMenu.look}),
393
395
  // Item highlighting: the navbar is built in the browser, so the
394
396
  // config has to travel to site.js rather than being rendered here.
395
397
  ...(navMenu.highlight && {highlight: navMenu.highlight}),
@@ -1205,6 +1207,8 @@ export async function renderBlogPage(templatePath, data = {}, seoMeta = {}) {
1205
1207
  // wires it; width and autohide also shape the body below, from the first paint.
1206
1208
  ...(navMenu.dock && {dock: navMenu.dock}),
1207
1209
  ...(navMenu.mobile && {mobile: navMenu.mobile}),
1210
+ // Bar shape and card dropdowns - drawn by menu-cards.mjs in the browser.
1211
+ ...(navMenu.look && {look: navMenu.look}),
1208
1212
  // Item highlighting: the navbar is built in the browser, so the
1209
1213
  // config has to travel to site.js rather than being rendered here.
1210
1214
  ...(navMenu.highlight && {highlight: navMenu.highlight}),
@@ -30,6 +30,9 @@
30
30
  <!-- Menu item hover / current-page effects. Loaded after site.css so a
31
31
  menu's own highlight wins over the blanket link styling there. -->
32
32
  <link rel="stylesheet" href="/public/css/menu-highlight.css?v=20261024-menu-highlight-fix">
33
+ <link rel="stylesheet" href="/public/css/menu-cards.css?v=20261029-menu-cards">
34
+ <link rel="stylesheet" href="/public/css/footer-showcase.css?v=20261029-footer-showcase">
35
+ <link rel="stylesheet" href="/public/css/page-motion.css?v=20261029-page-motion">
33
36
 
34
37
  <!-- Font overrides -->
35
38
  {{fontStyleTag}}
@@ -185,7 +188,7 @@
185
188
  <script src="/public/js/form-logic-engine.js?v=20261025-dropzone-disable" defer></script>
186
189
 
187
190
  <!-- Site initialisation -->
188
- <script src="/public/js/site.js?v=20261025-dconfig-click2" type="module"></script>
191
+ <script src="/public/js/site.js?v=20261029-page-motion" type="module"></script>
189
192
  <script src="/public/js/collection-context.js?v=20261010-utf8-payloads" type="module"></script>
190
193
  {{ctxMenusModule}}
191
194