@drawnagency/primitives 0.1.65 → 0.1.67
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/dist/chunk-4VMAZZXT.js +968 -0
- package/dist/{chunk-QYQ3DQHI.js → chunk-KM6HOW4H.js} +127 -40
- package/dist/{chunk-CBWK3KPV.js → chunk-VU3XR362.js} +4 -0
- package/dist/{chunk-FECCYOPJ.js → chunk-WJ7RZ6CC.js} +12 -3
- package/dist/{chunk-VMDKWUMT.js → chunk-XNGG5AGI.js} +74 -17
- package/dist/components/primitives/ResolvedMedia.d.ts +3 -1
- package/dist/components/primitives/ResolvedMedia.d.ts.map +1 -1
- package/dist/components/primitives/defineHeadingSection.d.ts +2 -0
- package/dist/components/primitives/defineHeadingSection.d.ts.map +1 -1
- package/dist/components/primitives/index.js +3 -3
- package/dist/components/sections/Button/index.d.ts.map +1 -1
- package/dist/components/sections/Colors/index.d.ts.map +1 -1
- package/dist/components/sections/Colors/schema.d.ts.map +1 -1
- package/dist/components/sections/Container/index.d.ts.map +1 -1
- package/dist/components/sections/DoDontMedia/index.d.ts.map +1 -1
- package/dist/components/sections/IconList/IconList.d.ts +2 -1
- package/dist/components/sections/IconList/IconList.d.ts.map +1 -1
- package/dist/components/sections/IconList/IconListSettings.d.ts +2 -1
- package/dist/components/sections/IconList/IconListSettings.d.ts.map +1 -1
- package/dist/components/sections/IconList/index.d.ts +1 -0
- package/dist/components/sections/IconList/index.d.ts.map +1 -1
- package/dist/components/sections/LinkHeading/index.d.ts.map +1 -1
- package/dist/components/sections/Media/MediaBlock.d.ts.map +1 -1
- package/dist/components/sections/Media/index.d.ts.map +1 -1
- package/dist/components/sections/Prose/index.d.ts.map +1 -1
- package/dist/components/sections/Spacer/index.d.ts.map +1 -1
- package/dist/components/sections/SubHeading/index.d.ts.map +1 -1
- package/dist/components/sections/SubSubHeading/index.d.ts.map +1 -1
- package/dist/components/sections/all-sections.d.ts +1 -0
- package/dist/components/sections/all-sections.d.ts.map +1 -1
- package/dist/components/sections/brand-guide.d.ts +1 -0
- package/dist/components/sections/brand-guide.d.ts.map +1 -1
- package/dist/components/sections/brand-guide.js +3 -3
- package/dist/components/sections/register-schemas.js +12 -942
- package/dist/components/sections/register.js +36 -0
- package/dist/components/shell/EditorLoading.d.ts +13 -0
- package/dist/components/shell/EditorLoading.d.ts.map +1 -0
- package/dist/components/shell/EditorShell.d.ts.map +1 -1
- package/dist/components/shell/SiteSettingsDisplay.d.ts.map +1 -1
- package/dist/hooks/useResolvedMedia.d.ts +2 -0
- package/dist/hooks/useResolvedMedia.d.ts.map +1 -1
- package/dist/index.js +21 -21
- package/dist/lib/index.js +2 -2
- package/dist/lib/insert-menu.d.ts +19 -0
- package/dist/lib/insert-menu.d.ts.map +1 -0
- package/dist/lib/registry.d.ts +23 -0
- package/dist/lib/registry.d.ts.map +1 -1
- package/dist/media/index.js +1 -1
- package/dist/media/resolve.d.ts.map +1 -1
- package/dist/types/database.d.ts +248 -34
- package/dist/types/database.d.ts.map +1 -1
- package/package.json +5 -1
- package/src/components/primitives/ResolvedMedia.tsx +51 -7
- package/src/components/primitives/defineHeadingSection.tsx +18 -2
- package/src/components/sections/Button/index.tsx +10 -3
- package/src/components/sections/Colors/index.tsx +15 -7
- package/src/components/sections/Colors/schema.ts +5 -2
- package/src/components/sections/Container/index.tsx +19 -3
- package/src/components/sections/DoDontMedia/index.tsx +18 -7
- package/src/components/sections/IconList/IconList.tsx +43 -19
- package/src/components/sections/IconList/IconListSettings.tsx +58 -11
- package/src/components/sections/IconList/index.tsx +51 -7
- package/src/components/sections/LinkHeading/index.tsx +2 -0
- package/src/components/sections/Media/MediaBlock.tsx +7 -0
- package/src/components/sections/Media/index.tsx +15 -6
- package/src/components/sections/Prose/index.tsx +9 -1
- package/src/components/sections/Spacer/index.tsx +2 -0
- package/src/components/sections/SubHeading/index.tsx +2 -0
- package/src/components/sections/SubSubHeading/index.tsx +2 -0
- package/src/components/shared/PasswordInput.tsx +3 -3
- package/src/components/shell/EditorLoading.tsx +37 -0
- package/src/components/shell/EditorShell.tsx +15 -20
- package/src/components/shell/SiteSettingsDisplay.tsx +28 -2
- package/src/hooks/useResolvedMedia.ts +9 -3
- package/src/lib/insert-menu.ts +42 -0
- package/src/lib/registry.ts +24 -0
- package/src/media/resolve.ts +4 -0
- package/src/types/database.ts +236 -36
- package/dist/{chunk-ZYXLNJ5M.js → chunk-AFK45HX2.js} +3 -3
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
MediaBlock,
|
|
10
10
|
containerGridClass,
|
|
11
11
|
useEditableCollection
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-XNGG5AGI.js";
|
|
13
13
|
import {
|
|
14
14
|
AddIcon,
|
|
15
15
|
DeleteIcon,
|
|
@@ -51,8 +51,8 @@ var ColorSpaceSchema = z.object({
|
|
|
51
51
|
{ message: "At least one color space must be defined" }
|
|
52
52
|
);
|
|
53
53
|
var ColorItemSchema = z.object({
|
|
54
|
-
name: z.string().optional(),
|
|
55
|
-
spaces: z.array(ColorSpaceSchema).min(1)
|
|
54
|
+
name: z.string().describe("Optional display name for this color (e.g. 'Brand Primary').").optional(),
|
|
55
|
+
spaces: z.array(ColorSpaceSchema).describe("One or more color-space definitions (hex/rgb/cmyk/pantone) for this color.").min(1)
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
// src/components/brandguide/Colors.tsx
|
|
@@ -329,12 +329,14 @@ function pluralize(n, word) {
|
|
|
329
329
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
330
330
|
var schema = z2.object({
|
|
331
331
|
type: z2.literal("colors"),
|
|
332
|
-
content: z2.object({
|
|
332
|
+
content: z2.object({
|
|
333
|
+
colors: z2.array(ColorItemSchema).describe("The list of brand colors, each with one or more color-space values (hex/rgb/cmyk/pantone).")
|
|
334
|
+
}),
|
|
333
335
|
options: z2.object({
|
|
334
|
-
label: z2.string().optional(),
|
|
335
|
-
columns: z2.number().int().min(2).max(4).optional(),
|
|
336
|
-
collapsing: z2.boolean().optional(),
|
|
337
|
-
showLabel: z2.boolean().optional()
|
|
336
|
+
label: z2.string().describe("Optional heading shown above the palette.").optional(),
|
|
337
|
+
columns: z2.number().int().min(2).max(4).describe("Number of swatch columns (2\u20134).").optional(),
|
|
338
|
+
collapsing: z2.boolean().describe("When true, use the compact collapsing swatch layout.").optional(),
|
|
339
|
+
showLabel: z2.boolean().describe("When true, show the palette label.").optional()
|
|
338
340
|
}).optional()
|
|
339
341
|
});
|
|
340
342
|
var Colors_default = defineSection({
|
|
@@ -343,6 +345,7 @@ var Colors_default = defineSection({
|
|
|
343
345
|
label: "Colors",
|
|
344
346
|
icon: /* @__PURE__ */ jsx3(Palette, { size: 18 }),
|
|
345
347
|
schema,
|
|
348
|
+
authoringNote: "A brand color palette. Each color may carry hex/rgb/cmyk/pantone values. Use to document brand colors with swatches.",
|
|
346
349
|
component: ({ content, options, onChange, openModal }) => /* @__PURE__ */ jsx3(
|
|
347
350
|
Colors,
|
|
348
351
|
{
|
|
@@ -377,7 +380,7 @@ var Colors_default = defineSection({
|
|
|
377
380
|
|
|
378
381
|
// src/components/sections/IconList/index.tsx
|
|
379
382
|
import { z as z3 } from "zod";
|
|
380
|
-
import { List } from "lucide-react";
|
|
383
|
+
import { List, Columns2 } from "lucide-react";
|
|
381
384
|
|
|
382
385
|
// src/components/sections/IconList/IconList.tsx
|
|
383
386
|
import { useRef as useRef3, useEffect as useEffect4, useState as useState3, useCallback } from "react";
|
|
@@ -514,6 +517,7 @@ function IconList({
|
|
|
514
517
|
icon = null,
|
|
515
518
|
showLabel = true,
|
|
516
519
|
stackText = false,
|
|
520
|
+
dodont,
|
|
517
521
|
labelClassName = "font-bold text-base-contrast",
|
|
518
522
|
textClassName = "text-base-contrast-light",
|
|
519
523
|
iconClassName = "text-primary",
|
|
@@ -526,11 +530,11 @@ function IconList({
|
|
|
526
530
|
onChange?.({
|
|
527
531
|
type: "icon_list",
|
|
528
532
|
content: { items: newItems },
|
|
529
|
-
options: { icon, showLabel, stackText }
|
|
533
|
+
options: { icon, showLabel, stackText, dodont }
|
|
530
534
|
});
|
|
531
535
|
onItemsChange?.(newItems);
|
|
532
536
|
},
|
|
533
|
-
[onChange, onItemsChange, icon, showLabel, stackText]
|
|
537
|
+
[onChange, onItemsChange, icon, showLabel, stackText, dodont]
|
|
534
538
|
);
|
|
535
539
|
if (!isEditMode) {
|
|
536
540
|
return /* @__PURE__ */ jsx6(
|
|
@@ -540,6 +544,7 @@ function IconList({
|
|
|
540
544
|
defaultIcon: icon,
|
|
541
545
|
showLabel,
|
|
542
546
|
stackText,
|
|
547
|
+
dodont,
|
|
543
548
|
labelClassName,
|
|
544
549
|
textClassName,
|
|
545
550
|
iconClassName
|
|
@@ -553,6 +558,7 @@ function IconList({
|
|
|
553
558
|
defaultIcon: icon,
|
|
554
559
|
showLabel,
|
|
555
560
|
stackText,
|
|
561
|
+
dodont,
|
|
556
562
|
labelClassName,
|
|
557
563
|
textClassName,
|
|
558
564
|
iconClassName,
|
|
@@ -560,15 +566,20 @@ function IconList({
|
|
|
560
566
|
}
|
|
561
567
|
);
|
|
562
568
|
}
|
|
563
|
-
function resolveIcon(item, defaultIcon) {
|
|
569
|
+
function resolveIcon(item, defaultIcon, sectionDodont) {
|
|
564
570
|
if (item.dodont === "do") return getIcon("check") ?? null;
|
|
565
571
|
if (item.dodont === "dont") return getIcon("x") ?? null;
|
|
566
|
-
|
|
567
|
-
|
|
572
|
+
if (item.icon) return getIcon(item.icon) ?? null;
|
|
573
|
+
if (sectionDodont === "do") return getIcon("check") ?? null;
|
|
574
|
+
if (sectionDodont === "dont") return getIcon("x") ?? null;
|
|
575
|
+
return defaultIcon ? getIcon(defaultIcon) : null;
|
|
568
576
|
}
|
|
569
|
-
function resolveIconColor(item, iconClassName) {
|
|
577
|
+
function resolveIconColor(item, iconClassName, sectionDodont) {
|
|
570
578
|
if (item.dodont === "do") return "text-green-600";
|
|
571
579
|
if (item.dodont === "dont") return "text-red-600";
|
|
580
|
+
if (item.icon) return iconClassName;
|
|
581
|
+
if (sectionDodont === "do") return "text-green-600";
|
|
582
|
+
if (sectionDodont === "dont") return "text-red-600";
|
|
572
583
|
return iconClassName;
|
|
573
584
|
}
|
|
574
585
|
function ViewIconList({
|
|
@@ -576,14 +587,15 @@ function ViewIconList({
|
|
|
576
587
|
defaultIcon,
|
|
577
588
|
showLabel,
|
|
578
589
|
stackText,
|
|
590
|
+
dodont,
|
|
579
591
|
labelClassName,
|
|
580
592
|
textClassName,
|
|
581
593
|
iconClassName
|
|
582
594
|
}) {
|
|
583
|
-
const hasAnyIcon = items.some((item) => resolveIcon(item, defaultIcon));
|
|
595
|
+
const hasAnyIcon = items.some((item) => resolveIcon(item, defaultIcon, dodont));
|
|
584
596
|
return /* @__PURE__ */ jsx6("div", { className: "grid gap-4 pb-4", children: items.map((item, i) => {
|
|
585
|
-
const iconEntry = resolveIcon(item, defaultIcon);
|
|
586
|
-
const iconColor = resolveIconColor(item, iconClassName);
|
|
597
|
+
const iconEntry = resolveIcon(item, defaultIcon, dodont);
|
|
598
|
+
const iconColor = resolveIconColor(item, iconClassName, dodont);
|
|
587
599
|
return /* @__PURE__ */ jsxs5(
|
|
588
600
|
"div",
|
|
589
601
|
{
|
|
@@ -625,6 +637,7 @@ function EditIconList({
|
|
|
625
637
|
defaultIcon,
|
|
626
638
|
showLabel,
|
|
627
639
|
stackText,
|
|
640
|
+
dodont,
|
|
628
641
|
labelClassName,
|
|
629
642
|
textClassName,
|
|
630
643
|
iconClassName,
|
|
@@ -669,6 +682,7 @@ function EditIconList({
|
|
|
669
682
|
hasAnyIcon,
|
|
670
683
|
showLabel,
|
|
671
684
|
stackText,
|
|
685
|
+
dodont,
|
|
672
686
|
labelClassName,
|
|
673
687
|
textClassName,
|
|
674
688
|
iconClassName,
|
|
@@ -711,6 +725,7 @@ function EditableRow({
|
|
|
711
725
|
hasAnyIcon,
|
|
712
726
|
showLabel,
|
|
713
727
|
stackText,
|
|
728
|
+
dodont,
|
|
714
729
|
labelClassName,
|
|
715
730
|
textClassName,
|
|
716
731
|
iconClassName,
|
|
@@ -727,9 +742,9 @@ function EditableRow({
|
|
|
727
742
|
const [pickerOpen, setPickerOpen] = useState3(false);
|
|
728
743
|
const [dodontOpen, setDodontOpen] = useState3(false);
|
|
729
744
|
const [editingSuppressed, setEditingSuppressed] = useState3(false);
|
|
730
|
-
const iconEntry = resolveIcon(item, defaultIcon);
|
|
745
|
+
const iconEntry = resolveIcon(item, defaultIcon, dodont);
|
|
731
746
|
const effectiveIconId = item.icon ?? defaultIcon ?? null;
|
|
732
|
-
const iconColor = resolveIconColor(item, iconClassName);
|
|
747
|
+
const iconColor = resolveIconColor(item, iconClassName, dodont);
|
|
733
748
|
useEffect4(() => {
|
|
734
749
|
const row = rowRef.current;
|
|
735
750
|
const handle = handleRef.current;
|
|
@@ -967,21 +982,59 @@ function TrailingDropZone({
|
|
|
967
982
|
|
|
968
983
|
// src/components/sections/IconList/IconListSettings.tsx
|
|
969
984
|
import { useState as useState4 } from "react";
|
|
985
|
+
import { Check as Check3, X as X3 } from "lucide-react";
|
|
970
986
|
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
971
987
|
function IconListSettings({
|
|
972
988
|
icon: initialIcon,
|
|
973
989
|
showLabel: initialShowLabel,
|
|
974
990
|
stackText: initialStackText,
|
|
991
|
+
dodont: initialDodont,
|
|
975
992
|
onChange
|
|
976
993
|
}) {
|
|
977
994
|
const [icon, setIcon] = useState4(initialIcon);
|
|
978
995
|
const [showLabel, setShowLabel] = useState4(initialShowLabel);
|
|
979
996
|
const [stackText, setStackText] = useState4(initialStackText);
|
|
997
|
+
const [dodont, setDodont] = useState4(initialDodont);
|
|
980
998
|
const [pickerOpen, setPickerOpen] = useState4(false);
|
|
981
|
-
const emit = (overrides) => onChange({ content: {}, options: { icon, showLabel, stackText, ...overrides } });
|
|
982
|
-
const showIcons = icon !== null;
|
|
999
|
+
const emit = (overrides) => onChange({ content: {}, options: { icon, showLabel, stackText, dodont, ...overrides } });
|
|
983
1000
|
const iconEntry = icon ? getIcon(icon) : null;
|
|
1001
|
+
const dodontActive = dodont === "do" || dodont === "dont";
|
|
1002
|
+
const tile = (value, label, aria, glyph, tint) => /* @__PURE__ */ jsxs6(
|
|
1003
|
+
"button",
|
|
1004
|
+
{
|
|
1005
|
+
type: "button",
|
|
1006
|
+
"aria-label": aria,
|
|
1007
|
+
"aria-pressed": dodont === value,
|
|
1008
|
+
className: cn(
|
|
1009
|
+
"cursor-pointer flex flex-col items-center gap-1 rounded border py-2 transition-colors",
|
|
1010
|
+
tint,
|
|
1011
|
+
dodont === value ? "border-primary bg-base-accent" : "border-base-200"
|
|
1012
|
+
),
|
|
1013
|
+
onClick: () => {
|
|
1014
|
+
setDodont(value);
|
|
1015
|
+
emit({ dodont: value });
|
|
1016
|
+
},
|
|
1017
|
+
children: [
|
|
1018
|
+
glyph,
|
|
1019
|
+
/* @__PURE__ */ jsx7("span", { className: "text-xs font-medium", children: label })
|
|
1020
|
+
]
|
|
1021
|
+
}
|
|
1022
|
+
);
|
|
984
1023
|
return /* @__PURE__ */ jsxs6("div", { className: "space-y-4", children: [
|
|
1024
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
1025
|
+
/* @__PURE__ */ jsx7(FormLabel, { children: "Do / Don't list" }),
|
|
1026
|
+
/* @__PURE__ */ jsxs6("div", { className: "grid grid-cols-3 gap-2", children: [
|
|
1027
|
+
tile(
|
|
1028
|
+
void 0,
|
|
1029
|
+
"None",
|
|
1030
|
+
"No do/don't",
|
|
1031
|
+
/* @__PURE__ */ jsx7("span", { className: "flex h-5 w-5 items-center justify-center rounded-sm border border-dashed border-base-contrast-light/40" }),
|
|
1032
|
+
"text-base-contrast-light"
|
|
1033
|
+
),
|
|
1034
|
+
tile("do", "Do", "Do list", /* @__PURE__ */ jsx7(Check3, { size: 20 }), "text-green-600"),
|
|
1035
|
+
tile("dont", "Don't", "Don't list", /* @__PURE__ */ jsx7(X3, { size: 20 }), "text-red-600")
|
|
1036
|
+
] })
|
|
1037
|
+
] }),
|
|
985
1038
|
/* @__PURE__ */ jsxs6("div", { className: "relative", children: [
|
|
986
1039
|
/* @__PURE__ */ jsx7(FormLabel, { htmlFor: "icon-picker-btn", children: "Default Icon" }),
|
|
987
1040
|
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
|
|
@@ -989,15 +1042,21 @@ function IconListSettings({
|
|
|
989
1042
|
"button",
|
|
990
1043
|
{
|
|
991
1044
|
id: "icon-picker-btn",
|
|
992
|
-
|
|
993
|
-
|
|
1045
|
+
disabled: dodontActive,
|
|
1046
|
+
className: cn(
|
|
1047
|
+
"flex items-center gap-2 rounded border border-base-200 px-3 py-1.5 text-sm text-base-contrast-light",
|
|
1048
|
+
dodontActive ? "cursor-not-allowed opacity-50" : "cursor-pointer hover:border-primary hover:text-primary"
|
|
1049
|
+
),
|
|
1050
|
+
onClick: () => {
|
|
1051
|
+
if (!dodontActive) setPickerOpen((prev) => !prev);
|
|
1052
|
+
},
|
|
994
1053
|
children: [
|
|
995
1054
|
iconEntry && /* @__PURE__ */ jsx7(iconEntry.icon, { size: 16 }),
|
|
996
1055
|
/* @__PURE__ */ jsx7("span", { children: iconEntry?.label ?? "None" })
|
|
997
1056
|
]
|
|
998
1057
|
}
|
|
999
1058
|
),
|
|
1000
|
-
icon && /* @__PURE__ */ jsx7(
|
|
1059
|
+
icon && !dodontActive && /* @__PURE__ */ jsx7(
|
|
1001
1060
|
"button",
|
|
1002
1061
|
{
|
|
1003
1062
|
className: "cursor-pointer text-xs text-base-contrast-light hover:text-base-contrast",
|
|
@@ -1009,7 +1068,8 @@ function IconListSettings({
|
|
|
1009
1068
|
}
|
|
1010
1069
|
)
|
|
1011
1070
|
] }),
|
|
1012
|
-
|
|
1071
|
+
dodontActive && /* @__PURE__ */ jsx7("p", { className: "mt-1 text-xs text-base-contrast-light/70", children: "Whole-list Do/Don't overrides the default icon." }),
|
|
1072
|
+
pickerOpen && !dodontActive && /* @__PURE__ */ jsx7("div", { className: "absolute top-full left-0 z-50 mt-1", children: /* @__PURE__ */ jsx7(
|
|
1013
1073
|
IconPicker,
|
|
1014
1074
|
{
|
|
1015
1075
|
selected: icon,
|
|
@@ -1060,20 +1120,40 @@ var IconListItemSchema = z3.object({
|
|
|
1060
1120
|
var schema2 = z3.object({
|
|
1061
1121
|
type: z3.literal("icon_list"),
|
|
1062
1122
|
content: z3.object({
|
|
1063
|
-
items: z3.array(IconListItemSchema)
|
|
1123
|
+
items: z3.array(IconListItemSchema).describe(
|
|
1124
|
+
"The list entries. Each item has a label, descriptive text, an optional icon, and an optional do/don't marker."
|
|
1125
|
+
)
|
|
1064
1126
|
}),
|
|
1065
1127
|
options: z3.object({
|
|
1066
|
-
icon: z3.string().nullable().optional(),
|
|
1067
|
-
showLabel: z3.boolean().optional(),
|
|
1068
|
-
stackText: z3.boolean().optional()
|
|
1128
|
+
icon: z3.string().nullable().describe("Default icon name applied to items that don't specify their own; null for no icon.").optional(),
|
|
1129
|
+
showLabel: z3.boolean().describe("When true, render each item's label.").optional(),
|
|
1130
|
+
stackText: z3.boolean().describe("When true, stack the label and text vertically instead of inline.").optional(),
|
|
1131
|
+
dodont: z3.enum(["do", "dont"]).describe("Whole-list do/don't mode: render every item with a green check (do) or red x (don't).").optional()
|
|
1069
1132
|
}).optional()
|
|
1070
1133
|
});
|
|
1134
|
+
var doDontListPreset = {
|
|
1135
|
+
id: "do_dont_list",
|
|
1136
|
+
label: "Do / Don't list",
|
|
1137
|
+
icon: /* @__PURE__ */ jsx8(Columns2, { size: 18 }),
|
|
1138
|
+
build: (newId) => ({
|
|
1139
|
+
type: "container",
|
|
1140
|
+
content: {
|
|
1141
|
+
columns: 2,
|
|
1142
|
+
flow: "row",
|
|
1143
|
+
children: [
|
|
1144
|
+
{ id: newId(), type: "icon_list", content: { items: [{ label: "", text: "" }] }, options: { dodont: "do" } },
|
|
1145
|
+
{ id: newId(), type: "icon_list", content: { items: [{ label: "", text: "" }] }, options: { dodont: "dont" } }
|
|
1146
|
+
]
|
|
1147
|
+
}
|
|
1148
|
+
})
|
|
1149
|
+
};
|
|
1071
1150
|
var IconList_default = defineSection({
|
|
1072
1151
|
type: "icon_list",
|
|
1073
1152
|
category: "brand-guide",
|
|
1074
1153
|
label: "Icon List",
|
|
1075
1154
|
icon: /* @__PURE__ */ jsx8(List, { size: 18 }),
|
|
1076
1155
|
schema: schema2,
|
|
1156
|
+
authoringNote: "A list of labeled items, optionally with per-item icons and do/don't markers. Use for feature lists, guidelines, or do/don't guidance.",
|
|
1077
1157
|
component: ({ content, options, onChange }) => /* @__PURE__ */ jsx8(
|
|
1078
1158
|
IconList,
|
|
1079
1159
|
{
|
|
@@ -1081,6 +1161,7 @@ var IconList_default = defineSection({
|
|
|
1081
1161
|
icon: options?.icon,
|
|
1082
1162
|
showLabel: options?.showLabel,
|
|
1083
1163
|
stackText: options?.stackText,
|
|
1164
|
+
dodont: options?.dodont,
|
|
1084
1165
|
onChange: onChange ? (c) => onChange(c) : void 0
|
|
1085
1166
|
}
|
|
1086
1167
|
),
|
|
@@ -1089,7 +1170,8 @@ var IconList_default = defineSection({
|
|
|
1089
1170
|
content: { items: [{ label: "", text: "" }] }
|
|
1090
1171
|
}),
|
|
1091
1172
|
getLabel: (content) => pluralize(content.content.items.length, "icon"),
|
|
1092
|
-
settingsForm: IconListSettings
|
|
1173
|
+
settingsForm: IconListSettings,
|
|
1174
|
+
presets: [doDontListPreset]
|
|
1093
1175
|
});
|
|
1094
1176
|
|
|
1095
1177
|
// src/components/sections/DoDontMedia/index.tsx
|
|
@@ -1097,11 +1179,11 @@ import { z as z4 } from "zod";
|
|
|
1097
1179
|
import { Image as ImageIcon } from "lucide-react";
|
|
1098
1180
|
|
|
1099
1181
|
// src/components/sections/DoDontMedia/DoDontMediaBlock.tsx
|
|
1100
|
-
import { Check as
|
|
1182
|
+
import { Check as Check4, X as X4 } from "lucide-react";
|
|
1101
1183
|
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1102
1184
|
function DoDontMediaBlock({ refValue, options, link, dodont, isEditMode, onRefChange }) {
|
|
1103
1185
|
return /* @__PURE__ */ jsxs7("div", { children: [
|
|
1104
|
-
/* @__PURE__ */ jsx9("div", { className: "flex h-10 items-center justify-center pb-1", children: dodont === "do" ? /* @__PURE__ */ jsx9(
|
|
1186
|
+
/* @__PURE__ */ jsx9("div", { className: "flex h-10 items-center justify-center pb-1", children: dodont === "do" ? /* @__PURE__ */ jsx9(Check4, { size: 28, className: "text-green-600" }) : /* @__PURE__ */ jsx9(X4, { size: 28, className: "text-red-600" }) }),
|
|
1105
1187
|
/* @__PURE__ */ jsx9(
|
|
1106
1188
|
MediaBlock,
|
|
1107
1189
|
{
|
|
@@ -1120,15 +1202,19 @@ import { jsx as jsx10 } from "react/jsx-runtime";
|
|
|
1120
1202
|
var schema3 = z4.object({
|
|
1121
1203
|
type: z4.literal("dodont_media"),
|
|
1122
1204
|
content: z4.object({
|
|
1123
|
-
ref: SingleMediaReferenceSchema
|
|
1124
|
-
|
|
1125
|
-
|
|
1205
|
+
ref: SingleMediaReferenceSchema.describe(
|
|
1206
|
+
"The image or video asset to display (a media reference by id). Required."
|
|
1207
|
+
),
|
|
1208
|
+
link: LinkValueSchema.describe(
|
|
1209
|
+
"Optional link wrapping the media \u2014 an internal page or a safe external URL."
|
|
1210
|
+
).optional(),
|
|
1211
|
+
dodont: z4.enum(["do", "dont"]).describe("Whether this is a 'do' (correct) or 'dont' (incorrect) example.")
|
|
1126
1212
|
}),
|
|
1127
1213
|
options: z4.object({
|
|
1128
|
-
square: z4.boolean().optional(),
|
|
1129
|
-
showCaption: z4.boolean().optional(),
|
|
1130
|
-
border: z4.boolean().optional(),
|
|
1131
|
-
objectFit: z4.enum(["cover", "contain"]).optional()
|
|
1214
|
+
square: z4.boolean().describe("When true, crop the media to a 1:1 square aspect ratio.").optional(),
|
|
1215
|
+
showCaption: z4.boolean().describe("When true, render the asset's caption beneath it.").optional(),
|
|
1216
|
+
border: z4.boolean().describe("When true, draw a border around the media.").optional(),
|
|
1217
|
+
objectFit: z4.enum(["cover", "contain"]).describe("How the image fills its box: 'contain' (fit whole image) or 'cover' (fill and crop).").optional()
|
|
1132
1218
|
}).default({})
|
|
1133
1219
|
});
|
|
1134
1220
|
var DoDontMedia_default = defineSection({
|
|
@@ -1137,6 +1223,7 @@ var DoDontMedia_default = defineSection({
|
|
|
1137
1223
|
category: "brand-guide",
|
|
1138
1224
|
icon: /* @__PURE__ */ jsx10(ImageIcon, { size: 18 }),
|
|
1139
1225
|
schema: schema3,
|
|
1226
|
+
authoringNote: "A single image or video tagged as a 'do' or 'don't' example. Use inside a Container to build side-by-side do/don't comparisons of visual usage.",
|
|
1140
1227
|
component: ({ content, options, onChange }) => /* @__PURE__ */ jsx10(
|
|
1141
1228
|
DoDontMediaBlock,
|
|
1142
1229
|
{
|
|
@@ -200,11 +200,15 @@ function resolveManifestReferences(content, manifest, sizes, provider) {
|
|
|
200
200
|
if ("srcSet" in resolved && resolved.srcSet) {
|
|
201
201
|
patch.srcset = resolved.srcSet;
|
|
202
202
|
}
|
|
203
|
+
patch.width = resolved.width;
|
|
204
|
+
patch.height = resolved.height;
|
|
203
205
|
} else if (resolved && resolved.tag === "video") {
|
|
204
206
|
patch.src = resolved.src;
|
|
205
207
|
if (resolved.poster) {
|
|
206
208
|
patch.poster = resolved.poster;
|
|
207
209
|
}
|
|
210
|
+
patch.width = resolved.width;
|
|
211
|
+
patch.height = resolved.height;
|
|
208
212
|
}
|
|
209
213
|
return { ...obj, ...patch };
|
|
210
214
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EditablePlainText
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XNGG5AGI.js";
|
|
4
4
|
import {
|
|
5
5
|
usePages
|
|
6
6
|
} from "./chunk-4E66N6UV.js";
|
|
@@ -39,7 +39,15 @@ function HeadingSection({ heading, tag, placeholder, className, onChange }) {
|
|
|
39
39
|
// src/components/primitives/defineHeadingSection.tsx
|
|
40
40
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
41
41
|
function defineHeadingSection(config) {
|
|
42
|
-
const
|
|
42
|
+
const heading = z.string().describe(
|
|
43
|
+
"The heading text. Plain text, one line; keep concise \u2014 it appears verbatim in the on-page heading and (unless excluded) the navigation."
|
|
44
|
+
);
|
|
45
|
+
const content = config.navExclusion ? z.object({
|
|
46
|
+
heading,
|
|
47
|
+
excludeFromNav: z.boolean().describe(
|
|
48
|
+
"When true, this heading is omitted from the generated navigation tree while still rendering on the page."
|
|
49
|
+
).optional()
|
|
50
|
+
}) : z.object({ heading });
|
|
43
51
|
const schema = z.object({ type: z.literal(config.type), content });
|
|
44
52
|
return defineSection({
|
|
45
53
|
type: config.type,
|
|
@@ -47,13 +55,14 @@ function defineHeadingSection(config) {
|
|
|
47
55
|
icon: config.icon,
|
|
48
56
|
schema,
|
|
49
57
|
navRole: config.navRole,
|
|
58
|
+
authoringNote: config.authoringNote,
|
|
50
59
|
component: ({ content: content2, onChange }) => /* @__PURE__ */ jsx2(
|
|
51
60
|
HeadingSection,
|
|
52
61
|
{
|
|
53
62
|
heading: content2.content.heading,
|
|
54
63
|
tag: config.tag,
|
|
55
64
|
placeholder: config.placeholder,
|
|
56
|
-
onChange: onChange ? (
|
|
65
|
+
onChange: onChange ? (heading2) => onChange({ ...content2, content: { ...content2.content, heading: heading2 } }) : void 0
|
|
57
66
|
}
|
|
58
67
|
),
|
|
59
68
|
defaults: () => ({ type: config.type, content: { heading: config.defaultHeading } }),
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "./chunk-I5737FJY.js";
|
|
8
8
|
import {
|
|
9
9
|
getMediaProvider
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-VU3XR362.js";
|
|
11
11
|
import {
|
|
12
12
|
cn
|
|
13
13
|
} from "./chunk-7EOSDFS3.js";
|
|
@@ -126,6 +126,7 @@ function EditablePlainText({
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
// src/components/primitives/ResolvedMedia.tsx
|
|
129
|
+
import { useState as useState2 } from "react";
|
|
129
130
|
import { ImageIcon } from "lucide-react";
|
|
130
131
|
|
|
131
132
|
// src/hooks/useResolvedMedia.ts
|
|
@@ -152,9 +153,11 @@ function useResolvedMedia(imageId) {
|
|
|
152
153
|
const item = manifestItem ?? pendingItem;
|
|
153
154
|
const alt = item?.alt ?? "";
|
|
154
155
|
const kind = item?.kind ?? "image";
|
|
156
|
+
const width = item?.width;
|
|
157
|
+
const height = item?.height;
|
|
155
158
|
const localUrl = pendingLocalUrls[imageId];
|
|
156
159
|
if (localUrl) {
|
|
157
|
-
return { src: localUrl, srcset: void 0, poster: void 0, alt, kind };
|
|
160
|
+
return { src: localUrl, srcset: void 0, poster: void 0, alt, kind, width, height };
|
|
158
161
|
}
|
|
159
162
|
if (manifestItem) {
|
|
160
163
|
const provider = getMediaProvider();
|
|
@@ -165,24 +168,28 @@ function useResolvedMedia(imageId) {
|
|
|
165
168
|
srcset: "srcSet" in resolved ? resolved.srcSet : void 0,
|
|
166
169
|
poster: void 0,
|
|
167
170
|
alt,
|
|
168
|
-
kind
|
|
171
|
+
kind,
|
|
172
|
+
width: resolved.width,
|
|
173
|
+
height: resolved.height
|
|
169
174
|
};
|
|
170
175
|
}
|
|
171
176
|
if (resolved && resolved.tag === "video") {
|
|
172
|
-
return { src: resolved.src, srcset: void 0, poster: resolved.poster, alt, kind };
|
|
177
|
+
return { src: resolved.src, srcset: void 0, poster: resolved.poster, alt, kind, width: resolved.width, height: resolved.height };
|
|
173
178
|
}
|
|
174
179
|
}
|
|
175
|
-
return { src: void 0, srcset: void 0, poster: void 0, alt, kind };
|
|
180
|
+
return { src: void 0, srcset: void 0, poster: void 0, alt, kind, width, height };
|
|
176
181
|
}, [imageId, ctx]);
|
|
177
182
|
}
|
|
178
183
|
|
|
179
184
|
// src/components/primitives/ResolvedMedia.tsx
|
|
180
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
185
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
181
186
|
function ResolvedMedia({
|
|
182
187
|
imageId,
|
|
183
188
|
src: propSrc,
|
|
184
189
|
srcset: propSrcset,
|
|
185
190
|
alt: propAlt,
|
|
191
|
+
width: propWidth,
|
|
192
|
+
height: propHeight,
|
|
186
193
|
className,
|
|
187
194
|
imgClassName,
|
|
188
195
|
invertFrom
|
|
@@ -193,22 +200,66 @@ function ResolvedMedia({
|
|
|
193
200
|
const poster = resolved.poster;
|
|
194
201
|
const alt = propAlt ?? resolved.alt;
|
|
195
202
|
const kind = resolved.kind;
|
|
203
|
+
const width = propWidth ?? resolved.width;
|
|
204
|
+
const height = propHeight ?? resolved.height;
|
|
205
|
+
const [loaded, setLoaded] = useState2(false);
|
|
196
206
|
const invertClass = invertFrom === "light" ? "invert dark:invert-0" : invertFrom === "dark" ? "dark:invert" : void 0;
|
|
197
|
-
const mediaClass = cn("h-full w-full", imgClassName, invertClass);
|
|
198
|
-
return /* @__PURE__ */ jsx("div", { className
|
|
207
|
+
const mediaClass = cn("relative h-full w-full", imgClassName, invertClass);
|
|
208
|
+
return /* @__PURE__ */ jsx("div", { className: cn("relative", className), children: src ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
209
|
+
/* @__PURE__ */ jsx(
|
|
210
|
+
"div",
|
|
211
|
+
{
|
|
212
|
+
"aria-hidden": "true",
|
|
213
|
+
"data-testid": "media-placeholder",
|
|
214
|
+
className: cn(
|
|
215
|
+
"pointer-events-none absolute inset-0 bg-base-accent transition-opacity duration-300",
|
|
216
|
+
loaded ? "opacity-0" : "opacity-100"
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
),
|
|
220
|
+
kind === "video" ? /* @__PURE__ */ jsx(
|
|
221
|
+
"video",
|
|
222
|
+
{
|
|
223
|
+
src,
|
|
224
|
+
poster,
|
|
225
|
+
width,
|
|
226
|
+
height,
|
|
227
|
+
muted: true,
|
|
228
|
+
playsInline: true,
|
|
229
|
+
loop: true,
|
|
230
|
+
autoPlay: true,
|
|
231
|
+
className: mediaClass,
|
|
232
|
+
onLoadedData: () => setLoaded(true)
|
|
233
|
+
}
|
|
234
|
+
) : /* @__PURE__ */ jsx(
|
|
235
|
+
"img",
|
|
236
|
+
{
|
|
237
|
+
src,
|
|
238
|
+
srcSet: srcset,
|
|
239
|
+
alt,
|
|
240
|
+
width,
|
|
241
|
+
height,
|
|
242
|
+
loading: "lazy",
|
|
243
|
+
decoding: "async",
|
|
244
|
+
className: mediaClass,
|
|
245
|
+
onLoad: () => setLoaded(true),
|
|
246
|
+
onError: () => setLoaded(true)
|
|
247
|
+
}
|
|
248
|
+
)
|
|
249
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "flex aspect-video h-full w-full flex-col items-center justify-center gap-1 rounded bg-base-accent text-base-contrast-light/50", children: [
|
|
199
250
|
/* @__PURE__ */ jsx(ImageIcon, { size: 24 }),
|
|
200
251
|
/* @__PURE__ */ jsx("span", { className: "text-sm", children: "No Image" })
|
|
201
252
|
] }) });
|
|
202
253
|
}
|
|
203
254
|
|
|
204
255
|
// src/components/primitives/ImageDropZone.tsx
|
|
205
|
-
import { useState as
|
|
206
|
-
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
256
|
+
import { useState as useState3 } from "react";
|
|
257
|
+
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
207
258
|
var ACCEPTED = /^(image|video)\//;
|
|
208
259
|
function ImageDropZone({ onImageSelected, className, children }) {
|
|
209
260
|
const mediaLibrary = useMediaLibrary();
|
|
210
|
-
const [dragging, setDragging] =
|
|
211
|
-
if (!mediaLibrary) return /* @__PURE__ */ jsx2(
|
|
261
|
+
const [dragging, setDragging] = useState3(false);
|
|
262
|
+
if (!mediaLibrary) return /* @__PURE__ */ jsx2(Fragment2, { children });
|
|
212
263
|
const maxFileSize = mediaLibrary.siteConfig?.media.maxFileSize;
|
|
213
264
|
const hasFiles = (e) => e.dataTransfer.types.includes("Files");
|
|
214
265
|
const handleDragOver = (e) => {
|
|
@@ -265,6 +316,9 @@ function MediaBlock({ refValue, options, link, isEditMode, onRefChange }) {
|
|
|
265
316
|
const captionStr = refValue.caption ? Array.isArray(refValue.caption) ? refValue.caption.join("\n") : refValue.caption : "";
|
|
266
317
|
const replace = onRefChange ? (imageId) => onRefChange({ ...refValue, imageId }) : void 0;
|
|
267
318
|
const baked = refValue;
|
|
319
|
+
const bakedWidth = typeof baked.width === "number" ? baked.width : void 0;
|
|
320
|
+
const bakedHeight = typeof baked.height === "number" ? baked.height : void 0;
|
|
321
|
+
const aspectRatio = bakedWidth && bakedHeight && !options.square ? `${bakedWidth} / ${bakedHeight}` : void 0;
|
|
268
322
|
const resolved = /* @__PURE__ */ jsx3(
|
|
269
323
|
ResolvedMedia,
|
|
270
324
|
{
|
|
@@ -272,6 +326,8 @@ function MediaBlock({ refValue, options, link, isEditMode, onRefChange }) {
|
|
|
272
326
|
src: baked.src,
|
|
273
327
|
srcset: baked.srcset,
|
|
274
328
|
alt: baked.alt,
|
|
329
|
+
width: bakedWidth,
|
|
330
|
+
height: bakedHeight,
|
|
275
331
|
className: "h-full w-full",
|
|
276
332
|
imgClassName: fitClass,
|
|
277
333
|
invertFrom: refValue.invertFrom
|
|
@@ -293,6 +349,7 @@ function MediaBlock({ refValue, options, link, isEditMode, onRefChange }) {
|
|
|
293
349
|
options.square && "aspect-square",
|
|
294
350
|
onImageClick && "cursor-pointer"
|
|
295
351
|
),
|
|
352
|
+
style: aspectRatio ? { aspectRatio } : void 0,
|
|
296
353
|
onClick: onImageClick,
|
|
297
354
|
onPointerDown: onImageClick ? (e) => e.stopPropagation() : void 0,
|
|
298
355
|
children: media
|
|
@@ -313,7 +370,7 @@ function MediaBlock({ refValue, options, link, isEditMode, onRefChange }) {
|
|
|
313
370
|
}
|
|
314
371
|
|
|
315
372
|
// src/components/primitives/EditableGrid.tsx
|
|
316
|
-
import { useRef as useRef4, useEffect as useEffect4, useState as
|
|
373
|
+
import { useRef as useRef4, useEffect as useEffect4, useState as useState5 } from "react";
|
|
317
374
|
import { ImageIcon as ImageIcon2 } from "lucide-react";
|
|
318
375
|
|
|
319
376
|
// src/lib/container-grid.ts
|
|
@@ -344,7 +401,7 @@ var spacerHiddenClass = {
|
|
|
344
401
|
};
|
|
345
402
|
|
|
346
403
|
// src/components/primitives/useEditableCollection.ts
|
|
347
|
-
import { useState as
|
|
404
|
+
import { useState as useState4, useCallback as useCallback3, useRef as useRef3, useEffect as useEffect3 } from "react";
|
|
348
405
|
var nextId = 0;
|
|
349
406
|
function uid() {
|
|
350
407
|
return typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : `_id_${nextId++}_${Date.now()}`;
|
|
@@ -357,7 +414,7 @@ function useEditableCollection({
|
|
|
357
414
|
onChange,
|
|
358
415
|
createItem
|
|
359
416
|
}) {
|
|
360
|
-
const [wrappedItems, setWrappedItems] =
|
|
417
|
+
const [wrappedItems, setWrappedItems] = useState4(
|
|
361
418
|
() => wrapItems(items)
|
|
362
419
|
);
|
|
363
420
|
const prevItemsRef = useRef3(items);
|
|
@@ -437,8 +494,8 @@ function EditableGrid({
|
|
|
437
494
|
onChange,
|
|
438
495
|
createItem
|
|
439
496
|
});
|
|
440
|
-
const [dragState, setDragState] =
|
|
441
|
-
const [isDragging, setIsDragging] =
|
|
497
|
+
const [dragState, setDragState] = useState5({ sourceId: null, closestEdge: null });
|
|
498
|
+
const [isDragging, setIsDragging] = useState5(false);
|
|
442
499
|
useEffect4(() => {
|
|
443
500
|
let cleanup;
|
|
444
501
|
let cancelled = false;
|
|
@@ -3,10 +3,12 @@ interface ResolvedMediaProps {
|
|
|
3
3
|
src?: string;
|
|
4
4
|
srcset?: string;
|
|
5
5
|
alt?: string;
|
|
6
|
+
width?: number;
|
|
7
|
+
height?: number;
|
|
6
8
|
className?: string;
|
|
7
9
|
imgClassName?: string;
|
|
8
10
|
invertFrom?: string;
|
|
9
11
|
}
|
|
10
|
-
export declare function ResolvedMedia({ imageId, src: propSrc, srcset: propSrcset, alt: propAlt, className, imgClassName, invertFrom, }: ResolvedMediaProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export declare function ResolvedMedia({ imageId, src: propSrc, srcset: propSrcset, alt: propAlt, width: propWidth, height: propHeight, className, imgClassName, invertFrom, }: ResolvedMediaProps): import("react/jsx-runtime").JSX.Element;
|
|
11
13
|
export {};
|
|
12
14
|
//# sourceMappingURL=ResolvedMedia.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResolvedMedia.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/ResolvedMedia.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ResolvedMedia.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/ResolvedMedia.tsx"],"names":[],"mappings":"AAKA,UAAU,kBAAkB;IAC1B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,UAAU,EAClB,SAAS,EACT,YAAY,EACZ,UAAU,GACX,EAAE,kBAAkB,2CAsEpB"}
|
|
@@ -11,6 +11,8 @@ interface HeadingSectionConfig<T extends string> {
|
|
|
11
11
|
defaultHeading: string;
|
|
12
12
|
/** When true, adds the `excludeFromNav` content field plus its settings toggle. */
|
|
13
13
|
navExclusion?: boolean;
|
|
14
|
+
/** Per-type authoring note surfaced by get_section_schema. */
|
|
15
|
+
authoringNote: string;
|
|
14
16
|
}
|
|
15
17
|
/**
|
|
16
18
|
* Factory for the heading section family (link / sub / sub-sub). They differ only
|