@omniharmonic/openspace-cli 0.1.9 → 0.1.10

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.
@@ -20445,6 +20445,8 @@ var NavPageSchema = external_exports.strictObject({
20445
20445
  page: PageIdSchema,
20446
20446
  /** Defaults to the page title. */
20447
20447
  label: NavLabelSchema.optional(),
20448
+ /** A section on that page (`#framework`): the entry scrolls to it. */
20449
+ anchor: external_exports.string().regex(/^[A-Za-z][A-Za-z0-9_-]*$/).optional(),
20448
20450
  hidden: external_exports.boolean().optional()
20449
20451
  });
20450
20452
  var NavCollectionSchema = external_exports.strictObject({
@@ -22505,6 +22507,58 @@ var BUTTON_STYLES = [
22505
22507
  "text-arrow"
22506
22508
  ];
22507
22509
  var MOTION_LEVELS = ["none", "subtle", "expressive"];
22510
+ var TYPE_SCALE_PRESETS = [...TYPE_PRESETS, "button", "nav", "wordmark"];
22511
+ var FONT_ROLES = ["heading", "body", "label"];
22512
+ var TEXT_CASES = ["none", "uppercase", "lowercase", "capitalize"];
22513
+ var WebFontSchema = named(
22514
+ "WebFont",
22515
+ "A Google Fonts family for a font role: family name, category, weights and whether italics load.",
22516
+ external_exports.strictObject({
22517
+ family: external_exports.string().regex(/^[A-Za-z0-9][A-Za-z0-9 ]{0,59}$/, { message: "Use the family's Google Fonts name" }),
22518
+ category: external_exports.enum(["serif", "sans-serif", "monospace"]),
22519
+ weights: external_exports.array(external_exports.int().min(100).max(900)).min(1).max(9).optional(),
22520
+ italic: external_exports.boolean().optional()
22521
+ })
22522
+ );
22523
+ var TypeStepSchema = named(
22524
+ "TypeStep",
22525
+ "A tuned typography preset: size (px at desktop and on phones), line height, letter spacing (em), case, weight, italic, font role.",
22526
+ external_exports.strictObject({
22527
+ size: external_exports.number().min(9).max(220).optional(),
22528
+ sizeMobile: external_exports.number().min(9).max(160).optional(),
22529
+ lineHeight: external_exports.number().min(0.7).max(3).optional(),
22530
+ letterSpacing: external_exports.number().min(-0.2).max(1).optional(),
22531
+ case: external_exports.enum(TEXT_CASES).optional(),
22532
+ weight: external_exports.int().min(100).max(900).optional(),
22533
+ italic: external_exports.boolean().optional(),
22534
+ font: external_exports.enum(FONT_ROLES).optional()
22535
+ })
22536
+ );
22537
+ var TypographyChoicesSchema = named(
22538
+ "TypographyChoices",
22539
+ "Fine typography: Google Fonts per role (heading, body, label), a tuned type scale, eyebrow color.",
22540
+ external_exports.strictObject({
22541
+ heading: WebFontSchema.optional(),
22542
+ body: WebFontSchema.optional(),
22543
+ /** Eyebrows, buttons and navigation (defaults to the body font). */
22544
+ label: WebFontSchema.optional(),
22545
+ scale: external_exports.partialRecord(external_exports.enum(TYPE_SCALE_PRESETS), TypeStepSchema).optional(),
22546
+ /** Eyebrow color: the accent/link color (default) or the muted text color. */
22547
+ eyebrowColor: external_exports.enum(["accent", "muted"]).optional()
22548
+ })
22549
+ );
22550
+ var LayoutChoicesSchema = named(
22551
+ "LayoutChoices",
22552
+ "Page rhythm: content width and narrow width (px), section padding (px at desktop and on phones), side gutter.",
22553
+ external_exports.strictObject({
22554
+ contentWidth: external_exports.int().min(480).max(2400).optional(),
22555
+ narrowWidth: external_exports.int().min(360).max(1600).optional(),
22556
+ sectionPadding: external_exports.int().min(0).max(320).optional(),
22557
+ sectionPaddingMobile: external_exports.int().min(0).max(240).optional(),
22558
+ gutter: external_exports.int().min(0).max(160).optional(),
22559
+ gutterMobile: external_exports.int().min(0).max(80).optional()
22560
+ })
22561
+ );
22508
22562
  var StyleChoicesSchema = named(
22509
22563
  "StyleChoices",
22510
22564
  "Site Styles selections (palette, font pairing, density, shape, buttons, motion, image treatment).",
@@ -22525,7 +22579,11 @@ var StyleChoicesSchema = named(
22525
22579
  /** An uploaded font family (`Styles.fonts`) used for headings instead of the pairing's. */
22526
22580
  headingFont: external_exports.string().max(60).optional(),
22527
22581
  /** An uploaded font family used for body text instead of the pairing's. */
22528
- bodyFont: external_exports.string().max(60).optional()
22582
+ bodyFont: external_exports.string().max(60).optional(),
22583
+ /** Fine typography: Google Fonts per role and a tuned type scale (imports set it). */
22584
+ typography: TypographyChoicesSchema.optional(),
22585
+ /** Page rhythm: content width and section padding (imports set it). */
22586
+ layout: LayoutChoicesSchema.optional()
22529
22587
  })
22530
22588
  );
22531
22589
  var FONT_CATEGORIES = [
@@ -23451,7 +23509,7 @@ function fontStack(spec) {
23451
23509
  }
23452
23510
  function pairingFamilies(p2) {
23453
23511
  const merged = /* @__PURE__ */ new Map();
23454
- for (const spec of [p2.heading, p2.body]) {
23512
+ for (const spec of [p2.heading, p2.body, ...p2.label ? [p2.label] : []]) {
23455
23513
  const prev = merged.get(spec.family);
23456
23514
  if (!prev) {
23457
23515
  merged.set(spec.family, { ...spec, weights: [...spec.weights] });
@@ -23561,7 +23619,8 @@ var TYPE_PRESET_NAMES = [
23561
23619
  "small",
23562
23620
  "eyebrow",
23563
23621
  "button",
23564
- "nav"
23622
+ "nav",
23623
+ "wordmark"
23565
23624
  ];
23566
23625
  var FLUID_TYPE = {
23567
23626
  minViewport: 360,
@@ -23583,7 +23642,8 @@ var PRESET_STEP = {
23583
23642
  small: -1,
23584
23643
  eyebrow: -1,
23585
23644
  button: -0.5,
23586
- nav: -0.5
23645
+ nav: -0.5,
23646
+ wordmark: 1
23587
23647
  };
23588
23648
  var LINE_HEIGHT = {
23589
23649
  display: 1.05,
@@ -23596,7 +23656,8 @@ var LINE_HEIGHT = {
23596
23656
  small: 1.5,
23597
23657
  eyebrow: 1.3,
23598
23658
  button: 1.2,
23599
- nav: 1.3
23659
+ nav: 1.3,
23660
+ wordmark: 1.1
23600
23661
  };
23601
23662
  var MIN_FONT_SIZE_PX = 14;
23602
23663
  var HEADINGS = /* @__PURE__ */ new Set(["display", "h1", "h2", "h3", "h4"]);
@@ -23629,7 +23690,7 @@ function typeScale(p2) {
23629
23690
  const sizes = stepSizes(PRESET_STEP[name]);
23630
23691
  const min = Math.max(MIN_FONT_SIZE_PX, sizes.min);
23631
23692
  const max = Math.max(MIN_FONT_SIZE_PX, sizes.max);
23632
- const heading2 = HEADINGS.has(name);
23693
+ const heading2 = HEADINGS.has(name) || name === "wordmark";
23633
23694
  let letterSpacing = "0em";
23634
23695
  if (LARGE_HEADINGS.has(name)) letterSpacing = p2.headingTracking;
23635
23696
  else if (heading2) letterSpacing = halfTracking(p2.headingTracking);
@@ -23639,8 +23700,9 @@ function typeScale(p2) {
23639
23700
  if (heading2) weight = "var(--os-font-weight-heading)";
23640
23701
  else if (name === "eyebrow" || name === "button" || name === "nav")
23641
23702
  weight = "var(--os-font-weight-strong)";
23703
+ const label3 = name === "eyebrow" || name === "button" || name === "nav";
23642
23704
  out[name] = {
23643
- "font-family": heading2 ? "var(--os-font-heading)" : "var(--os-font-body)",
23705
+ "font-family": heading2 ? "var(--os-font-heading)" : label3 ? "var(--os-font-label)" : "var(--os-font-body)",
23644
23706
  "font-size": fluidClamp(min, max),
23645
23707
  "line-height": String(LINE_HEIGHT[name]),
23646
23708
  "letter-spacing": letterSpacing,
@@ -23654,11 +23716,32 @@ function fontTokens(p2) {
23654
23716
  return {
23655
23717
  heading: fontStack(p2.heading),
23656
23718
  body: fontStack(p2.body),
23719
+ // Eyebrows, buttons and navigation: a third family when the site has one, else the body's.
23720
+ label: p2.label ? fontStack(p2.label) : "var(--os-font-body)",
23657
23721
  "weight-heading": String(p2.headingWeight),
23658
23722
  "weight-body": String(p2.bodyWeight),
23659
23723
  "weight-strong": String(p2.strongWeight)
23660
23724
  };
23661
23725
  }
23726
+ function mobileSize(desktopPx) {
23727
+ const base = FLUID_TYPE.maxBase;
23728
+ const px = desktopPx <= base ? desktopPx * 0.94 : FLUID_TYPE.minBase * (desktopPx / base) ** 0.75;
23729
+ return Math.round(px * 10) / 10;
23730
+ }
23731
+ function tunedPreset(step) {
23732
+ const out = {};
23733
+ if (step.size !== void 0) {
23734
+ const max = step.size;
23735
+ const min = step.sizeMobile ?? Math.min(max, mobileSize(max));
23736
+ out["font-size"] = fluidClamp(min, max);
23737
+ }
23738
+ if (step.lineHeight !== void 0) out["line-height"] = String(r4(step.lineHeight));
23739
+ if (step.letterSpacing !== void 0) out["letter-spacing"] = `${r4(step.letterSpacing)}em`;
23740
+ if (step.case !== void 0) out["text-transform"] = step.case;
23741
+ if (step.weight !== void 0) out["font-weight"] = String(step.weight);
23742
+ if (step.font !== void 0) out["font-family"] = `var(--os-font-${step.font})`;
23743
+ return out;
23744
+ }
23662
23745
 
23663
23746
  // ../theme/src/layout.ts
23664
23747
  var rem = (px) => px === 0 ? "0" : `${Math.round(px / 16 * 1e4) / 1e4}rem`;
@@ -24008,6 +24091,8 @@ var TOKEN_VARS = {
24008
24091
  font: {
24009
24092
  heading: varName("font", "heading"),
24010
24093
  body: varName("font", "body"),
24094
+ /** Eyebrows, buttons and navigation (the body font unless the site has a label font). */
24095
+ label: varName("font", "label"),
24011
24096
  weightHeading: varName("font", "weight", "heading"),
24012
24097
  weightBody: varName("font", "weight", "body"),
24013
24098
  weightStrong: varName("font", "weight", "strong")
@@ -24031,6 +24116,8 @@ var TOKEN_VARS = {
24031
24116
  wide: varName("width", "wide")
24032
24117
  },
24033
24118
  radius: record2(RADIUS_NAMES, (r2) => varName("radius", r2)),
24119
+ /** Eyebrow text color: the link color, or muted text (`choices.typography.eyebrowColor`). */
24120
+ eyebrowColor: varName("eyebrow", "color"),
24034
24121
  shadow: record2(SHADOW_NAMES, (s) => varName("shadow", s)),
24035
24122
  /** Buttons: `--os-button-<primary|secondary|tertiary>-<prop>`. */
24036
24123
  button: record2(
@@ -24468,6 +24555,7 @@ function compileStyles(styles, options = {}) {
24468
24555
  });
24469
24556
  pairing2 = getPairing(DEFAULT_PAIRING_ID);
24470
24557
  }
24558
+ pairing2 = withWebFonts(pairing2, choices.typography);
24471
24559
  const accentHex = scaleHex(palette.accent);
24472
24560
  const neutralHex = scaleHex(palette.neutral);
24473
24561
  const root = /* @__PURE__ */ new Map();
@@ -24489,16 +24577,29 @@ function compileStyles(styles, options = {}) {
24489
24577
  }
24490
24578
  for (const [k, v2] of Object.entries(fonts)) root.set(varName("font", k), v2);
24491
24579
  const type = typeScale(pairing2);
24580
+ const tuned = choices.typography?.scale ?? {};
24492
24581
  for (const preset of TYPE_PRESET_NAMES) {
24493
- for (const [prop, v2] of Object.entries(type[preset]))
24494
- root.set(varName("type", preset, prop), v2);
24582
+ const step = tuned[preset];
24583
+ const values = step ? { ...type[preset], ...tunedPreset(step) } : type[preset];
24584
+ for (const [prop, v2] of Object.entries(values)) root.set(varName("type", preset, prop), v2);
24495
24585
  }
24496
24586
  root.set(varName("measure"), "70ch");
24497
24587
  for (const [k, v2] of Object.entries(spaceTokens(choices.density)))
24498
24588
  root.set(varName("space", k), v2);
24499
- for (const [k, v2] of Object.entries(sectionTokens(choices.density)))
24500
- root.set(varName("section", k), v2);
24501
- for (const [k, v2] of Object.entries(WIDTH_TOKENS)) root.set(varName("width", k), v2);
24589
+ const rhythm = sectionTokens(choices.density);
24590
+ const lay = choices.layout;
24591
+ if (lay?.sectionPadding !== void 0)
24592
+ rhythm["pad-y"] = fluidClamp(
24593
+ lay.sectionPaddingMobile ?? Math.round(lay.sectionPadding * 0.55),
24594
+ lay.sectionPadding
24595
+ );
24596
+ if (lay?.gutter !== void 0)
24597
+ rhythm.gutter = fluidClamp(lay.gutterMobile ?? Math.min(lay.gutter, 20), lay.gutter);
24598
+ for (const [k, v2] of Object.entries(rhythm)) root.set(varName("section", k), v2);
24599
+ const widths = { ...WIDTH_TOKENS };
24600
+ if (lay?.contentWidth !== void 0) widths.content = `${lay.contentWidth}px`;
24601
+ if (lay?.narrowWidth !== void 0) widths.narrow = `${lay.narrowWidth}px`;
24602
+ for (const [k, v2] of Object.entries(widths)) root.set(varName("width", k), v2);
24502
24603
  for (const [k, v2] of Object.entries(radiusTokens(choices.shape)))
24503
24604
  root.set(varName("radius", k), v2);
24504
24605
  for (const [k, v2] of Object.entries(SHADOW_VALUES)) root.set(varName("shadow", k), v2);
@@ -24512,6 +24613,10 @@ function compileStyles(styles, options = {}) {
24512
24613
  }
24513
24614
  for (const [k, v2] of Object.entries(IMAGE_TREATMENT_VALUES[choices.imageTreatment]))
24514
24615
  themed.set(varName("image", k), v2);
24616
+ themed.set(
24617
+ varName("eyebrow", "color"),
24618
+ choices.typography?.eyebrowColor === "muted" ? `var(${varName("color", "text-muted")})` : `var(${varName("color", "link")})`
24619
+ );
24515
24620
  const roles = themeRoles(palette);
24516
24621
  const custom2 = /* @__PURE__ */ new Map();
24517
24622
  const overriddenRoles = /* @__PURE__ */ new Map();
@@ -24658,6 +24763,40 @@ function compileStyles(styles, options = {}) {
24658
24763
  warnings
24659
24764
  };
24660
24765
  }
24766
+ function withWebFonts(pairing2, typography) {
24767
+ if (!typography?.heading && !typography?.body && !typography?.label) return pairing2;
24768
+ const spec = (font, wanted) => {
24769
+ const weights = [...new Set(font.weights ?? wanted)].sort((a, b) => a - b);
24770
+ return {
24771
+ family: font.family,
24772
+ category: font.category,
24773
+ weights,
24774
+ ...font.italic ? { italic: true } : {}
24775
+ };
24776
+ };
24777
+ const near = (weights, wanted) => weights.reduce((best, w) => Math.abs(w - wanted) < Math.abs(best - wanted) ? w : best);
24778
+ const scale = typography.scale ?? {};
24779
+ const out = { ...pairing2 };
24780
+ if (typography.heading) {
24781
+ const wanted = scale.h1?.weight ?? scale.h2?.weight ?? scale.display?.weight;
24782
+ out.heading = spec(typography.heading, [wanted ?? pairing2.headingWeight]);
24783
+ out.headingWeight = wanted ?? near(out.heading.weights, pairing2.headingWeight);
24784
+ }
24785
+ if (typography.body) {
24786
+ const wanted = scale.body?.weight;
24787
+ out.body = spec(typography.body, [wanted ?? 400, 600]);
24788
+ out.bodyWeight = wanted ?? near(out.body.weights, 400);
24789
+ out.strongWeight = near(
24790
+ out.body.weights.filter((w) => w > out.bodyWeight).concat(out.bodyWeight),
24791
+ 600
24792
+ );
24793
+ }
24794
+ if (typography.label) {
24795
+ const wanted = [scale.eyebrow, scale.button, scale.nav].map((s) => s?.weight).filter((w) => w !== void 0);
24796
+ out.label = spec(typography.label, wanted.length ? wanted : [400, 500]);
24797
+ }
24798
+ return out;
24799
+ }
24661
24800
  function block(selectors, decls, indent = "") {
24662
24801
  const lines = Object.entries(decls).map(([k, v2]) => `${indent} ${k}: ${v2};`);
24663
24802
  return `${indent}${selectors.join(`,
@@ -25967,8 +26106,9 @@ function resolveLeaf(item3, doc, basePath, currentId) {
25967
26106
  return {
25968
26107
  kind: "leaf",
25969
26108
  label: item3.label ?? page?.title ?? "Page",
25970
- href: page ? pagePath(page, basePath) : `${normalizeBasePath(basePath)}/`,
25971
- current: item3.page === currentId,
26109
+ href: `${page ? pagePath(page, basePath) : `${normalizeBasePath(basePath)}/`}${item3.anchor ? `#${item3.anchor}` : ""}`,
26110
+ // An entry for a section of a page isn't "this page".
26111
+ current: item3.page === currentId && !item3.anchor,
25972
26112
  newTab: false
25973
26113
  };
25974
26114
  }
@@ -26504,8 +26644,8 @@ ${typeClasses}
26504
26644
  }
26505
26645
  /* Large type never overflows a narrow column */
26506
26646
  @container block (max-width:34rem){
26507
- .os-type-display{font-size:min(${v(T.type.display["font-size"])},13cqi)}
26508
- .os-type-h1{font-size:min(${v(T.type.h1["font-size"])},10cqi)}
26647
+ .os-type-display{font-size:min(${v(T.type.display["font-size"])},16cqi)}
26648
+ .os-type-h1{font-size:min(${v(T.type.h1["font-size"])},12cqi)}
26509
26649
  }
26510
26650
  /* Layout helpers for block authors */
26511
26651
  .os-cluster{display:flex;flex-wrap:wrap;gap:${v(T.space.xs)};align-items:center}
@@ -26595,7 +26735,7 @@ ${button("tertiary")}
26595
26735
  .os-header__brand{display:inline-flex;align-items:center;flex:0 1 auto;min-width:0;color:${v(c2.heading)};text-decoration:none;margin-inline-end:auto}
26596
26736
  .os-header__logo{height:var(--mlogo-h,2rem);width:auto;border-radius:0;background:none}
26597
26737
  .os-header__logo .os-img__img{height:100%;width:auto;object-fit:contain}
26598
- .os-header__title{font-family:${v(T.font.heading)};font-weight:${v(T.font.weightHeading)};font-size:${v(T.type.h4["font-size"])};letter-spacing:${v(T.type.h4["letter-spacing"])};line-height:1.1;text-wrap:balance;overflow-wrap:break-word;max-inline-size:30ch}
26738
+ .os-header__title{${typePreset("wordmark")};text-wrap:balance;overflow-wrap:break-word;max-inline-size:30ch}
26599
26739
  .os-header__brand--split,.os-nav{display:none}
26600
26740
  .os-header__actions{display:none;align-items:center;gap:${v(T.space.xs)}}
26601
26741
  .os-header__actions .os-button{min-height:2.5rem;padding-block:0.5rem}
@@ -26891,7 +27031,7 @@ function renderPageHtml(opts) {
26891
27031
  const ogImage = ogImageSrc ? ogImageUrl(ogImageSrc, siteUrl, opts.imageMap) : void 0;
26892
27032
  const customHeading = chosenCustomFont(doc.styles, doc.styles.choices.headingFont);
26893
27033
  const customBody = chosenCustomFont(doc.styles, doc.styles.choices.bodyFont);
26894
- const noWebFonts = Boolean(customHeading && customBody);
27034
+ const noWebFonts = Boolean(customHeading && customBody && !styles.tokens.pairing.label);
26895
27035
  const inlineFonts = !noWebFonts && opts.fontCss ? opts.fontCss : "";
26896
27036
  const fonts = noWebFonts || inlineFonts ? [] : opts.fontStylesheets ?? [googleFontsUrl(styles.tokens.pairing)];
26897
27037
  const fontFaces = [inlineFonts, customFontFaces(doc.styles, (src) => mediaUrl(src, basePath))].filter(Boolean).join("\n");
@@ -29392,7 +29532,7 @@ var columnsBlock = defineBlock({
29392
29532
  fields: {
29393
29533
  items: f.list({
29394
29534
  min: 1,
29395
- max: 8,
29535
+ max: 12,
29396
29536
  itemLabel: "heading",
29397
29537
  fields: {
29398
29538
  image: f.image({ optional: true }),
@@ -29432,7 +29572,9 @@ var columnsBlock = defineBlock({
29432
29572
  options: [
29433
29573
  { value: "2", label: "2" },
29434
29574
  { value: "3", label: "3" },
29435
- { value: "4", label: "4" }
29575
+ { value: "4", label: "4" },
29576
+ { value: "5", label: "5" },
29577
+ { value: "6", label: "6" }
29436
29578
  ],
29437
29579
  default: "3",
29438
29580
  display: "segmented"
@@ -29870,15 +30012,15 @@ function productPrice(item3, locale) {
29870
30012
  }
29871
30013
  function PriceText({ price }) {
29872
30014
  return /* @__PURE__ */ jsxs15(Fragment7, { children: [
30015
+ price.was ? /* @__PURE__ */ jsx19("span", { className: "os-visually-hidden", children: "Sale price: " }) : null,
30016
+ /* @__PURE__ */ jsx19("span", { children: price.text }),
29873
30017
  price.was ? /* @__PURE__ */ jsxs15(Fragment7, { children: [
29874
- /* @__PURE__ */ jsxs15("s", { children: [
29875
- /* @__PURE__ */ jsx19("span", { className: "os-visually-hidden", children: "Was " }),
30018
+ " ",
30019
+ /* @__PURE__ */ jsxs15("s", { className: "os-price__was", children: [
30020
+ /* @__PURE__ */ jsx19("span", { className: "os-visually-hidden", children: ", was " }),
29876
30021
  price.was
29877
- ] }),
29878
- /* @__PURE__ */ jsx19("span", { className: "os-price__sep", "aria-hidden": "true", children: " \xB7 " }),
29879
- /* @__PURE__ */ jsx19("span", { className: "os-visually-hidden", children: /^\p{L}/u.test(price.text) ? ", sale price: " : "now " })
29880
- ] }) : null,
29881
- /* @__PURE__ */ jsx19("span", { children: price.text })
30022
+ ] })
30023
+ ] }) : null
29882
30024
  ] });
29883
30025
  }
29884
30026
  function eventWhen(fm, locale) {
@@ -29938,6 +30080,13 @@ var summaryBlock = defineBlock({
29938
30080
  }),
29939
30081
  columns: f.select({ options: ["2", "3", "4"], default: "3", display: "segmented" }),
29940
30082
  showImage: f.boolean({ default: true }),
30083
+ imageAspect: f.select({
30084
+ optional: true,
30085
+ options: ASPECT_OPTIONS.filter((o) => o.value !== "original"),
30086
+ default: "3:2",
30087
+ label: "Photo shape",
30088
+ help: "Crop of the photos in the grid and card layouts (portrait suits clothing and books)"
30089
+ }),
29941
30090
  showDate: f.boolean({ default: true }),
29942
30091
  showExcerpt: f.boolean({ default: true }),
29943
30092
  showMeta: f.boolean({ default: false, help: "Author, client, location or episode" }),
@@ -29986,7 +30135,7 @@ var summaryBlock = defineBlock({
29986
30135
  {
29987
30136
  src: image3,
29988
30137
  alt: "",
29989
- aspect: variant === "wall" ? "original" : variant === "list" ? "4:3" : "3:2",
30138
+ aspect: variant === "wall" ? "original" : variant === "list" ? "4:3" : fields.imageAspect ?? "3:2",
29990
30139
  sizes: sizesFor(variant, columns2),
29991
30140
  className: "os-summary__image"
29992
30141
  }
@@ -30273,7 +30422,7 @@ var collectionsCss = `
30273
30422
  .os-summary__excerpt{margin:0.2em 0 0;color:var(--os-color-text)}
30274
30423
  .os-price__sep{color:var(--os-color-text-muted);font-weight:400}
30275
30424
  .os-summary__price{margin:0;font-weight:var(--os-font-weight-strong);color:var(--os-color-heading)}
30276
- .os-summary__price s{font-weight:400;color:var(--os-color-text-muted)}
30425
+ .os-summary__price s{font-weight:400;color:var(--os-color-text-muted);text-decoration-line:line-through}
30277
30426
  .os-summary__image{transition:transform var(--os-motion-duration-slow) var(--os-motion-ease)}
30278
30427
  .os-summary__empty,.os-events__empty{margin:0;color:var(--os-color-text-muted)}
30279
30428
  .os-summary__foot{margin-top:var(--os-space-2xs)}
@@ -30713,6 +30862,12 @@ var productBlock = defineBlock({
30713
30862
  help: "Pick one product from a products collection"
30714
30863
  }),
30715
30864
  showDescription: f.boolean({ default: true }),
30865
+ showTitle: f.boolean({
30866
+ optional: true,
30867
+ default: true,
30868
+ label: "Show the name",
30869
+ help: "Off on the product's own page, where the page title already names it"
30870
+ }),
30716
30871
  quantity: f.boolean({ default: true, label: "Quantity picker" }),
30717
30872
  buttonLabel: f.text({ maxLength: 30, default: "Add to cart" }),
30718
30873
  detailsLabel: f.text({ maxLength: 30, default: "View details" })
@@ -30784,7 +30939,7 @@ var productBlock = defineBlock({
30784
30939
  }
30785
30940
  ) : null,
30786
30941
  /* @__PURE__ */ jsxs17("div", { className: "os-product__body", children: [
30787
- /* @__PURE__ */ jsx21(
30942
+ fields.showTitle !== false ? /* @__PURE__ */ jsx21(
30788
30943
  "h3",
30789
30944
  {
30790
30945
  className: cx(
@@ -30793,7 +30948,7 @@ var productBlock = defineBlock({
30793
30948
  ),
30794
30949
  children: /* @__PURE__ */ jsx21("a", { className: "os-product__link", href, children: fm.title })
30795
30950
  }
30796
- ),
30951
+ ) : null,
30797
30952
  price ? /* @__PURE__ */ jsx21("p", { className: "os-product__price", children: /* @__PURE__ */ jsx21(PriceText, { price }) }) : null,
30798
30953
  fields.showDescription && fm.excerpt ? /* @__PURE__ */ jsx21("p", { className: "os-product__desc", children: fm.excerpt }) : null,
30799
30954
  firstAvailable && !canSell ? /* @__PURE__ */ jsx21(
@@ -30858,13 +31013,13 @@ var productBlock = defineBlock({
30858
31013
  )
30859
31014
  ] })
30860
31015
  ] }) : options.length ? /* @__PURE__ */ jsx21("p", { className: "os-product__soldout", children: "Sold out" }) : /* @__PURE__ */ jsx21(EditorNotice, { children: "Give this product a SKU so it can be added to the cart." }),
30861
- /* @__PURE__ */ jsxs17("a", { className: "os-product__details", href, children: [
31016
+ fields.detailsLabel ? /* @__PURE__ */ jsxs17("a", { className: "os-product__details", href, children: [
30862
31017
  fields.detailsLabel,
30863
31018
  /* @__PURE__ */ jsxs17("span", { className: "os-visually-hidden", children: [
30864
31019
  ": ",
30865
31020
  fm.title
30866
31021
  ] })
30867
- ] })
31022
+ ] }) : null
30868
31023
  ] })
30869
31024
  ] });
30870
31025
  }
@@ -31052,7 +31207,7 @@ var commerceCss = `
31052
31207
  .os-product__link{color:inherit;text-decoration:none}
31053
31208
  .os-product__link:hover{text-decoration:underline;text-underline-offset:0.2em}
31054
31209
  .os-product__price{display:flex;flex-wrap:wrap;gap:0 0.3em;align-items:baseline;margin:0;font-size:var(--os-type-lead-font-size);font-weight:var(--os-font-weight-strong);color:var(--os-color-heading);font-variant-numeric:lining-nums}
31055
- .os-product__price s{font-weight:400;color:var(--os-color-text-muted)}
31210
+ .os-product__price s{font-weight:400;color:var(--os-color-text-muted);text-decoration-line:line-through}
31056
31211
  .os-product__desc{margin:0;color:var(--os-color-text);max-inline-size:var(--os-measure)}
31057
31212
  .os-product__buy{display:grid;gap:var(--os-space-xs);margin-top:var(--os-space-2xs)}
31058
31213
  .os-product__row{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--os-space-xs)}
@@ -32105,7 +32260,7 @@ var headingBlock = defineBlock({
32105
32260
  size: f.select({ options: SIZES2, default: "auto", label: "Visual size" }),
32106
32261
  subheading: f.text({ optional: true, multiline: true, maxLength: 280 })
32107
32262
  },
32108
- variants: ["plain", "rule", "underline", "split"],
32263
+ variants: ["plain", "rule", "underline", "split", "eyebrow-rule"],
32109
32264
  styleSlots: ["colorTheme", "padding", "align", "animation", "typography.heading"],
32110
32265
  defaults: {
32111
32266
  fields: {
@@ -32115,7 +32270,7 @@ var headingBlock = defineBlock({
32115
32270
  },
32116
32271
  ai: {
32117
32272
  purpose: "A section heading with optional eyebrow and supporting line.",
32118
- whenToUse: "To open a section or introduce a group of blocks. `rule` adds a short accent line above, `underline` a line below, `split` puts the subheading beside the heading on wide screens.",
32273
+ whenToUse: "To open a section or introduce a group of blocks. `rule` adds a short accent line above, `eyebrow-rule` a short accent line between the eyebrow and the heading, `underline` a line below, `split` puts the subheading beside the heading on wide screens.",
32119
32274
  avoid: "Using headings for emphasis inside body copy (use text); skipping levels (h2 \u2192 h4); more than one Heading 1 per page."
32120
32275
  },
32121
32276
  render: ({ fields, variant, style }) => {
@@ -32249,7 +32404,9 @@ var dividerBlock = defineBlock({
32249
32404
  var headingCss = `
32250
32405
  .os-heading{display:grid;gap:var(--os-space-xs)}
32251
32406
  .os-heading__main{display:grid;gap:var(--os-space-2xs)}
32252
- .os-heading__eyebrow{color:var(--os-color-link);margin:0}
32407
+ .os-heading__eyebrow{color:var(--os-eyebrow-color,var(--os-color-link));margin:0}
32408
+ .os-heading--eyebrow-rule .os-heading__eyebrow::after{content:"";display:block;width:clamp(3rem,5vw,4rem);height:2px;background:var(--os-color-accent);margin-block:clamp(1.25rem,2vw,1.75rem) clamp(0.75rem,1.5vw,1.25rem)}
32409
+ .os-align-center .os-heading--eyebrow-rule .os-heading__eyebrow::after,.os-malign-center .os-heading--eyebrow-rule .os-heading__eyebrow::after{margin-inline:auto}
32253
32410
  .os-heading__text{margin:0;text-wrap:balance;color:var(--os-color-heading)}
32254
32411
  .os-heading__sub{margin:0;color:var(--os-color-text);max-inline-size:var(--os-measure);text-wrap:pretty}
32255
32412
  .os-heading--rule .os-heading__main::before{content:"";width:2.5rem;height:3px;border-radius:var(--os-radius-full);background:var(--os-color-accent);margin-bottom:var(--os-space-2xs)}
@@ -49831,6 +49988,10 @@ export {
49831
49988
  SHAPES,
49832
49989
  BUTTON_STYLES,
49833
49990
  MOTION_LEVELS,
49991
+ TYPE_SCALE_PRESETS,
49992
+ WebFontSchema,
49993
+ TypeStepSchema,
49994
+ LayoutChoicesSchema,
49834
49995
  StyleChoicesSchema,
49835
49996
  StylesSchema,
49836
49997
  SiteDocumentSchema,
@@ -49840,6 +50001,7 @@ export {
49840
50001
  parseColor,
49841
50002
  toHex,
49842
50003
  deltaEOK,
50004
+ relativeLuminance,
49843
50005
  contrastRatio,
49844
50006
  nearestAccessible,
49845
50007
  TYPE_PAIRINGS,
@@ -49847,7 +50009,10 @@ export {
49847
50009
  pairingFamilies,
49848
50010
  flattenDtcg,
49849
50011
  compileStyles,
50012
+ itemDate,
50013
+ isLive,
49850
50014
  renderPageHtml,
50015
+ rt,
49851
50016
  blocksStyleTag,
49852
50017
  blockHeadings,
49853
50018
  copyViolations,
@@ -49967,4 +50132,4 @@ lucide/dist/esm/lucide.mjs:
49967
50132
  * See the LICENSE file in the root directory of this source tree.
49968
50133
  *)
49969
50134
  */
49970
- //# sourceMappingURL=chunk-KAJOS2YV.js.map
50135
+ //# sourceMappingURL=chunk-RD24SW4M.js.map