@driftime/sanity-plugin-handbook 0.3.2 → 0.4.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/dist/index.js CHANGED
@@ -1,9 +1,8 @@
1
+ import { createContext, createElement, useContext, useEffect, useRef, useState } from "react";
1
2
  import { CommandList, PreviewCard, SanityDefaultPreview, defineArrayMember, defineField, definePlugin, defineType, useClient, useCurrentUser, useSchema } from "sanity";
2
3
  import { c } from "react/compiler-runtime";
3
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
- import { createContext, createElement, useContext, useEffect, useRef, useState } from "react";
5
5
  import { Box, Button, Card, Flex, Heading, Layer, LayerProvider, Stack, Text, useClickOutsideEvent, useElementSize, useTheme_v2 } from "@sanity/ui";
6
- import { Code } from "@sanity/ui/code";
7
6
  import { Pane, PaneContent, PaneLayout } from "sanity/structure";
8
7
  import { PaneContext, PaneLayoutContext } from "sanity/_singletons";
9
8
  import { ArrowLeftIcon } from "@sanity/icons/ArrowLeft";
@@ -11,37 +10,16 @@ import { ChevronDownIcon } from "@sanity/icons/ChevronDown";
11
10
  import { ChevronRightIcon } from "@sanity/icons/ChevronRight";
12
11
  import { Popover } from "@sanity/ui/popover";
13
12
  import { PortableText } from "@portabletext/react";
14
- /** Properties every icon the plugin draws is rendered with. */
13
+ import { Code } from "@sanity/ui/code";
14
+ /**
15
+ * Properties the plugin's own icons are drawn with. Icons taken from `@sanity/icons` are left alone,
16
+ * since they already carry the sizing and stroke the rest of the Studio uses.
17
+ */
15
18
  const defaultIconProps = {
16
19
  width: "1em",
17
20
  height: "1em",
18
21
  strokeWidth: 1.5
19
22
  };
20
- function BookOpenTextIcon(props) {
21
- let $ = c(8), t0, t1, t2, t3, t4, t5;
22
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "M12 7v14" }), t1 = /* @__PURE__ */ jsx("path", { d: "M16 12h2" }), t2 = /* @__PURE__ */ jsx("path", { d: "M16 8h2" }), t3 = /* @__PURE__ */ jsx("path", { d: "M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z" }), t4 = /* @__PURE__ */ jsx("path", { d: "M6 12h2" }), t5 = /* @__PURE__ */ jsx("path", { d: "M6 8h2" }), $[0] = t0, $[1] = t1, $[2] = t2, $[3] = t3, $[4] = t4, $[5] = t5) : (t0 = $[0], t1 = $[1], t2 = $[2], t3 = $[3], t4 = $[4], t5 = $[5]);
23
- let t6;
24
- return $[6] === props ? t6 = $[7] : (t6 = /* @__PURE__ */ jsxs("svg", {
25
- xmlns: "http://www.w3.org/2000/svg",
26
- width: 24,
27
- height: 24,
28
- viewBox: "0 0 24 24",
29
- fill: "none",
30
- stroke: "currentColor",
31
- strokeWidth: 2,
32
- strokeLinecap: "round",
33
- strokeLinejoin: "round",
34
- ...props,
35
- children: [
36
- t0,
37
- t1,
38
- t2,
39
- t3,
40
- t4,
41
- t5
42
- ]
43
- }), $[6] = props, $[7] = t6), t6;
44
- }
45
23
  /**
46
24
  * Creates a Sanity Studio icon component from an SVG icon.
47
25
  *
@@ -59,123 +37,52 @@ function createSanityIcon(icon, props) {
59
37
  }
60
38
  return SanityIcon;
61
39
  }
62
- function PortableCode(t0) {
63
- let $ = c(8), props, style;
64
- $[0] === t0 ? (props = $[1], style = $[2]) : ({style, ...props} = t0, $[0] = t0, $[1] = props, $[2] = style);
65
- let t1;
66
- $[3] === style ? t1 = $[4] : (t1 = {
67
- paddingBlock: 2,
68
- paddingInline: 4,
69
- fontSize: "0.875em",
70
- backgroundColor: "var(--card-code-bg-color)",
71
- borderRadius: 2,
72
- ...style
73
- }, $[3] = style, $[4] = t1);
74
- let t2;
75
- return $[5] !== props || $[6] !== t1 ? (t2 = /* @__PURE__ */ jsx("code", {
76
- style: t1,
77
- ...props
78
- }), $[5] = props, $[6] = t1, $[7] = t2) : t2 = $[7], t2;
79
- }
80
- function CodeDecorator(t0) {
81
- let $ = c(2), { children } = t0, t1;
82
- return $[0] === children ? t1 = $[1] : (t1 = /* @__PURE__ */ jsx(PortableCode, { children }), $[0] = children, $[1] = t1), t1;
83
- }
84
- function ListItemStyle(t0) {
85
- let $ = c(3), { children } = t0, t1;
86
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t1 = { marginTop: "0.375em" }, $[0] = t1) : t1 = $[0];
87
- let t2;
88
- return $[1] === children ? t2 = $[2] : (t2 = /* @__PURE__ */ jsx(Text, {
89
- size: 1,
90
- style: t1,
91
- children
92
- }), $[1] = children, $[2] = t2), t2;
93
- }
94
- function PortableBlockquote(t0) {
95
- let $ = c(15), children, muted, props, style;
96
- $[0] === t0 ? (children = $[1], muted = $[2], props = $[3], style = $[4]) : ({muted, children, style, ...props} = t0, $[0] = t0, $[1] = children, $[2] = muted, $[3] = props, $[4] = style);
97
- let t1;
98
- $[5] === style ? t1 = $[6] : (t1 = {
99
- borderLeft: "2px solid var(--card-border-color)",
100
- ...style
101
- }, $[5] = style, $[6] = t1);
102
- let t2;
103
- $[7] === Symbol.for("react.memo_cache_sentinel") ? (t2 = { fontStyle: "italic" }, $[7] = t2) : t2 = $[7];
104
- let t3;
105
- $[8] !== children || $[9] !== muted ? (t3 = /* @__PURE__ */ jsx(Text, {
106
- size: 1,
107
- muted,
108
- style: t2,
109
- children
110
- }), $[8] = children, $[9] = muted, $[10] = t3) : t3 = $[10];
111
- let t4;
112
- return $[11] !== props || $[12] !== t1 || $[13] !== t3 ? (t4 = /* @__PURE__ */ jsx(Box, {
113
- paddingY: 1,
114
- paddingLeft: 3,
115
- style: t1,
116
- ...props,
117
- children: t3
118
- }), $[11] = props, $[12] = t1, $[13] = t3, $[14] = t4) : t4 = $[14], t4;
119
- }
120
- function PortableHeading(props) {
121
- let $ = c(2), t0;
122
- return $[0] === props ? t0 = $[1] : (t0 = /* @__PURE__ */ jsx(Text, {
123
- as: "h2",
124
- size: 1,
125
- weight: "medium",
126
- ...props
127
- }), $[0] = props, $[1] = t0), t0;
128
- }
129
- function PortableParagraph(props) {
130
- let $ = c(2), t0;
131
- return $[0] === props ? t0 = $[1] : (t0 = /* @__PURE__ */ jsx(Text, {
132
- size: 1,
133
- ...props
134
- }), $[0] = props, $[1] = t0), t0;
135
- }
136
- function ParagraphStyle(t0) {
137
- let $ = c(2), { children } = t0, t1;
138
- return $[0] === children ? t1 = $[1] : (t1 = /* @__PURE__ */ jsx(PortableParagraph, { children }), $[0] = children, $[1] = t1), t1;
139
- }
140
- function HeadingStyle(t0) {
141
- let $ = c(2), { children } = t0, t1;
142
- return $[0] === children ? t1 = $[1] : (t1 = /* @__PURE__ */ jsx(PortableHeading, { children }), $[0] = children, $[1] = t1), t1;
143
- }
144
- function BlockquoteStyle(t0) {
145
- let $ = c(2), { children } = t0, t1;
146
- return $[0] === children ? t1 = $[1] : (t1 = /* @__PURE__ */ jsx(PortableBlockquote, { children }), $[0] = children, $[1] = t1), t1;
40
+ /** Whether the plugin is running in a development build, which decides whether it reports what it recovered from. */
41
+ const isDevelopment = process.env.NODE_ENV === "development", prefixStyle = "color: #2276fc";
42
+ /**
43
+ * Creates the logger a package reports through, so every message names the plugin it came from and
44
+ * only a development build hears it. In a browser console the name is drawn in blue, the way the
45
+ * Studio's own messages are; a terminal ignores the styling and prints it plain.
46
+ *
47
+ * @param name - Name of the package the messages come from.
48
+ * @returns Functions that warn, report an error, or word a message for throwing.
49
+ */
50
+ function createLogger(name) {
51
+ let prefix = `[${name}]`;
52
+ /**
53
+ * Words a message so it names the package it came from.
54
+ *
55
+ * @param message - The message to word.
56
+ * @returns The message with the package name in front.
57
+ */
58
+ function format(message) {
59
+ return `${prefix} ${message}`;
60
+ }
61
+ return {
62
+ /**
63
+ * Reports something the plugin recovered from, in development only.
64
+ *
65
+ * @param message - What was recovered from and what to do about it.
66
+ */
67
+ warn(message) {
68
+ isDevelopment && console.warn(`%c${prefix}%c ${message}`, prefixStyle, "");
69
+ },
70
+ /**
71
+ * Reports something the plugin could not recover from, in development only.
72
+ *
73
+ * @param message - What went wrong and what to do about it.
74
+ */
75
+ error(message) {
76
+ isDevelopment && console.error(`%c${prefix}%c ${message}`, prefixStyle, "");
77
+ },
78
+ format
79
+ };
147
80
  }
148
- const linkAnnotation = defineArrayMember({
149
- name: "link",
150
- type: "object",
151
- description: "Link applied to the selected text.",
152
- preview: {
153
- select: { href: "href" },
154
- prepare(selection) {
155
- let { href } = selection;
156
- return { title: href ?? "Link" };
157
- }
158
- },
159
- fields: [defineField({
160
- name: "href",
161
- title: "URL",
162
- type: "url",
163
- description: "Web address destination for this link. Supports http, https, mailto, and tel schemes.",
164
- validation: (rule) => rule.uri({ scheme: [
165
- "http",
166
- "https",
167
- "mailto",
168
- "tel"
169
- ] })
170
- })]
171
- });
172
- function InfoIcon(props) {
81
+ /** Name the package is published under, which every message it reports carries. */
82
+ const pluginName = "@driftime/sanity-plugin-handbook", logger = createLogger(pluginName), guideTypeName = "handbook.guide", handbookTypeName = "handbook.handbook", imageTypeName = "handbook.image", videoTypeName = "handbook.video", codeTypeName = "handbook.code", calloutTypeName = "handbook.callout", horizontalRuleTypeName = "handbook.horizontalRule", singletonTypes = /* @__PURE__ */ new Set([handbookTypeName]), documentTypes = /* @__PURE__ */ new Set([handbookTypeName, guideTypeName]);
83
+ function BookTextIcon(props) {
173
84
  let $ = c(5), t0, t1, t2;
174
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("circle", {
175
- cx: "12",
176
- cy: "12",
177
- r: "10"
178
- }), t1 = /* @__PURE__ */ jsx("path", { d: "M12 16v-4" }), t2 = /* @__PURE__ */ jsx("path", { d: "M12 8h.01" }), $[0] = t0, $[1] = t1, $[2] = t2) : (t0 = $[0], t1 = $[1], t2 = $[2]);
85
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20" }), t1 = /* @__PURE__ */ jsx("path", { d: "M8 11h8" }), t2 = /* @__PURE__ */ jsx("path", { d: "M8 7h6" }), $[0] = t0, $[1] = t1, $[2] = t2) : (t0 = $[0], t1 = $[1], t2 = $[2]);
179
86
  let t3;
180
87
  return $[3] === props ? t3 = $[4] : (t3 = /* @__PURE__ */ jsxs("svg", {
181
88
  xmlns: "http://www.w3.org/2000/svg",
@@ -195,945 +102,105 @@ function InfoIcon(props) {
195
102
  ]
196
103
  }), $[3] = props, $[4] = t3), t3;
197
104
  }
198
- function LightbulbIcon(props) {
199
- let $ = c(5), t0, t1, t2;
200
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5" }), t1 = /* @__PURE__ */ jsx("path", { d: "M9 18h6" }), t2 = /* @__PURE__ */ jsx("path", { d: "M10 22h4" }), $[0] = t0, $[1] = t1, $[2] = t2) : (t0 = $[0], t1 = $[1], t2 = $[2]);
201
- let t3;
202
- return $[3] === props ? t3 = $[4] : (t3 = /* @__PURE__ */ jsxs("svg", {
203
- xmlns: "http://www.w3.org/2000/svg",
204
- width: 24,
205
- height: 24,
206
- viewBox: "0 0 24 24",
207
- fill: "none",
208
- stroke: "currentColor",
209
- strokeWidth: 2,
210
- strokeLinecap: "round",
211
- strokeLinejoin: "round",
212
- ...props,
213
- children: [
214
- t0,
215
- t1,
216
- t2
217
- ]
218
- }), $[3] = props, $[4] = t3), t3;
105
+ /**
106
+ * Checks whether a value is defined and non-empty, treating `false`, empty strings, and objects with
107
+ * no keys as absent. An array is absent unless one of its elements is itself present, while anything
108
+ * built from a class counts as present on existence alone. Not intended for boolean flags.
109
+ *
110
+ * @param value - The value to check.
111
+ * @returns True if the value is defined and not empty.
112
+ */
113
+ function isDefined(value) {
114
+ if (value == null || value === !1) return !1;
115
+ if (typeof value == "string") return value.trim() !== "";
116
+ if (Array.isArray(value)) return value.some((element) => isDefined(element));
117
+ if (typeof value == "object") {
118
+ let prototype = Reflect.getPrototypeOf(value);
119
+ return prototype !== Object.prototype && prototype !== null || Object.keys(value).length > 0;
120
+ }
121
+ return !0;
219
122
  }
220
- function TriangleAlertIcon(props) {
221
- let $ = c(5), t0, t1, t2;
222
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }), t1 = /* @__PURE__ */ jsx("path", { d: "M12 9v4" }), t2 = /* @__PURE__ */ jsx("path", { d: "M12 17h.01" }), $[0] = t0, $[1] = t1, $[2] = t2) : (t0 = $[0], t1 = $[1], t2 = $[2]);
223
- let t3;
224
- return $[3] === props ? t3 = $[4] : (t3 = /* @__PURE__ */ jsxs("svg", {
225
- xmlns: "http://www.w3.org/2000/svg",
226
- width: 24,
227
- height: 24,
228
- viewBox: "0 0 24 24",
229
- fill: "none",
230
- stroke: "currentColor",
231
- strokeWidth: 2,
232
- strokeLinecap: "round",
233
- strokeLinejoin: "round",
234
- ...props,
235
- children: [
236
- t0,
237
- t1,
238
- t2
239
- ]
240
- }), $[3] = props, $[4] = t3), t3;
123
+ /**
124
+ * Converts a string between different casing formats.
125
+ *
126
+ * @param value - The string to convert.
127
+ * @param format - The target casing format.
128
+ * @returns The converted string.
129
+ */
130
+ function convertCase(value, format) {
131
+ let words = value.replaceAll(/(?<lower>[a-z0-9])(?<upper>[A-Z])/gu, "$<lower> $<upper>").replaceAll(/[-_\s]+/gu, " ").trim().toLowerCase();
132
+ switch (format) {
133
+ case "kebab": return words.replaceAll(/\s+/gu, "-");
134
+ case "snake": return words.replaceAll(/\s+/gu, "_");
135
+ case "camel": return words.replaceAll(/\s+(?<character>.)/gu, (_match, character) => character.toUpperCase());
136
+ case "pascal": return words.replaceAll(/(?:^|\s+)(?<character>.)/gu, (_match, character) => character.toUpperCase());
137
+ case "title": return words.replaceAll(/\b\w/gu, (character) => character.toUpperCase());
138
+ case "sentence": return words.replaceAll(/^(?<character>.)/gu, (character) => character.toUpperCase());
139
+ default: return value;
140
+ }
241
141
  }
242
- /** Presentation for each callout variant. */
243
- const presentation = {
244
- tip: {
245
- icon: LightbulbIcon,
246
- tone: "positive"
247
- },
248
- info: {
249
- icon: InfoIcon,
250
- tone: "primary"
251
- },
252
- warning: {
253
- icon: TriangleAlertIcon,
254
- tone: "caution"
142
+ /**
143
+ * Checks whether a value can be read by key, narrowing what arrives untyped from outside the plugin.
144
+ *
145
+ * @param value - The value to check.
146
+ * @returns True if the value has keys to read.
147
+ */
148
+ function isRecord(value) {
149
+ return typeof value == "object" && !!value;
150
+ }
151
+ /**
152
+ * Reads a value out of nested records by following a path of keys, so a caller can name something
153
+ * inside a shape it does not otherwise know.
154
+ *
155
+ * @param value - The object to read from.
156
+ * @param path - Keys leading to the value.
157
+ * @returns The value at the path, or undefined when a key is missing or a step holds no keys to read.
158
+ */
159
+ function readPath(value, path) {
160
+ let current = value;
161
+ for (let segment of path) {
162
+ if (!isRecord(current)) return;
163
+ current = current[segment];
255
164
  }
256
- };
257
- function CalloutContent(t0) {
258
- let $ = c(17), children, props, variant;
259
- $[0] === t0 ? (children = $[1], props = $[2], variant = $[3]) : ({variant, children, ...props} = t0, $[0] = t0, $[1] = children, $[2] = props, $[3] = variant);
260
- let { icon: Icon, tone } = presentation[variant], t1;
261
- $[4] === Symbol.for("react.memo_cache_sentinel") ? (t1 = {
262
- flexShrink: 0,
263
- marginTop: "-2px",
264
- fontSize: "16px",
265
- color: "var(--card-icon-color)"
266
- }, $[4] = t1) : t1 = $[4];
267
- let t2;
268
- $[5] === Icon ? t2 = $[6] : (t2 = /* @__PURE__ */ jsx("div", {
269
- style: t1,
270
- children: /* @__PURE__ */ jsx(Icon, { ...defaultIconProps })
271
- }), $[5] = Icon, $[6] = t2);
272
- let t3;
273
- $[7] === Symbol.for("react.memo_cache_sentinel") ? (t3 = { color: "var(--card-icon-color)" }, $[7] = t3) : t3 = $[7];
274
- let t4;
275
- $[8] === children ? t4 = $[9] : (t4 = /* @__PURE__ */ jsx(Text, {
276
- size: 1,
277
- style: t3,
278
- children
279
- }), $[8] = children, $[9] = t4);
280
- let t5;
281
- $[10] !== t2 || $[11] !== t4 ? (t5 = /* @__PURE__ */ jsxs(Flex, {
282
- align: "flex-start",
283
- gap: 3,
284
- children: [t2, t4]
285
- }), $[10] = t2, $[11] = t4, $[12] = t5) : t5 = $[12];
286
- let t6;
287
- return $[13] !== props || $[14] !== t5 || $[15] !== tone ? (t6 = /* @__PURE__ */ jsx(Card, {
288
- padding: 4,
289
- radius: 2,
290
- tone,
291
- ...props,
292
- children: t5
293
- }), $[13] = props, $[14] = t5, $[15] = tone, $[16] = t6) : t6 = $[16], t6;
294
- }
295
- function CalloutPreview(t0) {
296
- let $ = c(8), { variant, body } = t0, t1 = variant ?? "tip", t2;
297
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t2 = {
298
- display: "flex",
299
- flexDirection: "column",
300
- gap: 12
301
- }, $[0] = t2) : t2 = $[0];
302
- let t3;
303
- $[1] === body ? t3 = $[2] : (t3 = body?.map(_temp2$1), $[1] = body, $[2] = t3);
304
- let t4;
305
- $[3] === t3 ? t4 = $[4] : (t4 = /* @__PURE__ */ jsx("div", {
306
- style: t2,
307
- children: t3
308
- }), $[3] = t3, $[4] = t4);
309
- let t5;
310
- return $[5] !== t1 || $[6] !== t4 ? (t5 = /* @__PURE__ */ jsx(CalloutContent, {
311
- variant: t1,
312
- children: t4
313
- }), $[5] = t1, $[6] = t4, $[7] = t5) : t5 = $[7], t5;
314
- }
315
- function _temp2$1(t0) {
316
- let { _key, children } = t0;
317
- return /* @__PURE__ */ jsx("div", {
318
- style: { whiteSpace: "pre-wrap" },
319
- children: children.map(_temp$3).join("")
320
- }, _key);
321
- }
322
- function _temp$3(child) {
323
- return child.text;
324
- }
325
- function MessageCircleIcon(props) {
326
- let $ = c(3), t0;
327
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719" }), $[0] = t0) : t0 = $[0];
328
- let t1;
329
- return $[1] === props ? t1 = $[2] : (t1 = /* @__PURE__ */ jsx("svg", {
330
- xmlns: "http://www.w3.org/2000/svg",
331
- width: 24,
332
- height: 24,
333
- viewBox: "0 0 24 24",
334
- fill: "none",
335
- stroke: "currentColor",
336
- strokeWidth: 2,
337
- strokeLinecap: "round",
338
- strokeLinejoin: "round",
339
- ...props,
340
- children: t0
341
- }), $[1] = props, $[2] = t1), t1;
342
- }
343
- /** Type name of the callout block. */
344
- const calloutTypeName = "handbook.callout", calloutType = defineType({
345
- name: calloutTypeName,
346
- type: "object",
347
- title: "Callout",
348
- icon: createSanityIcon(MessageCircleIcon),
349
- description: "Highlighted message block drawing attention to tips, supplementary information, or warnings.",
350
- components: { preview: CalloutPreview },
351
- preview: {
352
- select: {
353
- variant: "variant",
354
- body: "body"
355
- },
356
- prepare(selection) {
357
- let { variant, body } = selection;
358
- return {
359
- title: "Callout",
360
- variant,
361
- body
362
- };
363
- }
364
- },
365
- fields: [defineField({
366
- name: "variant",
367
- type: "string",
368
- description: "Visual style and intent of the callout.",
369
- initialValue: "tip",
370
- validation: (rule) => rule.required(),
371
- options: {
372
- list: [
373
- {
374
- title: "Tip",
375
- value: "tip"
376
- },
377
- {
378
- title: "Information",
379
- value: "info"
380
- },
381
- {
382
- title: "Warning",
383
- value: "warning"
384
- }
385
- ],
386
- layout: "radio",
387
- direction: "horizontal"
388
- }
389
- }), defineField({
390
- name: "body",
391
- type: "array",
392
- description: "Content displayed inside the callout. Supports inline formatting and links.",
393
- of: [defineArrayMember({
394
- name: "block",
395
- type: "block",
396
- styles: [{
397
- title: "Normal",
398
- value: "normal",
399
- component: ParagraphStyle
400
- }],
401
- lists: [],
402
- marks: {
403
- decorators: [
404
- {
405
- title: "Bold",
406
- value: "strong"
407
- },
408
- {
409
- title: "Italic",
410
- value: "em"
411
- },
412
- {
413
- title: "Strikethrough",
414
- value: "strike-through"
415
- },
416
- {
417
- title: "Code",
418
- value: "code",
419
- component: CodeDecorator
420
- }
421
- ],
422
- annotations: [linkAnnotation]
423
- }
424
- })]
425
- })]
426
- });
427
- function CodeContent(t0) {
428
- let $ = c(14), code, language, props, style;
429
- $[0] === t0 ? (code = $[1], language = $[2], props = $[3], style = $[4]) : ({code, language, style, ...props} = t0, $[0] = t0, $[1] = code, $[2] = language, $[3] = props, $[4] = style);
430
- let t1;
431
- $[5] === style ? t1 = $[6] : (t1 = {
432
- overflowX: "auto",
433
- ...style
434
- }, $[5] = style, $[6] = t1);
435
- let t2;
436
- $[7] !== code || $[8] !== language ? (t2 = /* @__PURE__ */ jsx(Code, {
437
- size: 1,
438
- language,
439
- children: code
440
- }), $[7] = code, $[8] = language, $[9] = t2) : t2 = $[9];
441
- let t3;
442
- return $[10] !== props || $[11] !== t1 || $[12] !== t2 ? (t3 = /* @__PURE__ */ jsx(Card, {
443
- padding: 4,
444
- radius: 2,
445
- tone: "transparent",
446
- style: t1,
447
- ...props,
448
- children: t2
449
- }), $[10] = props, $[11] = t1, $[12] = t2, $[13] = t3) : t3 = $[13], t3;
165
+ return current;
450
166
  }
167
+ /** Share of the available space the content pane takes relative to the sidebar. */
168
+ const contentSpacing = {
169
+ section: 48,
170
+ paragraph: 16,
171
+ heading: 48,
172
+ media: 24,
173
+ callout: 32,
174
+ blockquote: 32,
175
+ list: 32,
176
+ nestedList: 12,
177
+ rule: 40
178
+ }, assetUrlFragment = "\"asset\": { \"url\": asset.asset->url }", guideFragment = `...@-> {
179
+ ...,
180
+ content[] { ..., ${`
181
+ _type == "${imageTypeName}" => { ..., ${assetUrlFragment} },
182
+ _type == "${videoTypeName}" => { ..., ${assetUrlFragment} }
183
+ `} }
184
+ }`;
451
185
  /**
452
- * Checks whether a value is defined and non-empty, treating `false`, empty strings, and objects with
453
- * no keys as absent. An array is absent unless one of its elements is itself present, while anything
454
- * built from a class counts as present on existence alone. Not intended for boolean flags.
186
+ * Brands a GROQ query with the shape of the data it returns, so a fetch can infer its result type
187
+ * instead of being told it at every call site.
455
188
  *
456
- * @param value - The value to check.
457
- * @returns True if the value is defined and not empty.
189
+ * @param query - The GROQ query string.
190
+ * @returns The query, typed to the given result shape.
458
191
  */
459
- function isDefined(value) {
460
- if (value == null || value === !1) return !1;
461
- if (typeof value == "string") return value.trim() !== "";
462
- if (Array.isArray(value)) return value.some((element) => isDefined(element));
463
- if (typeof value == "object") {
464
- let prototype = Reflect.getPrototypeOf(value);
465
- return prototype !== Object.prototype && prototype !== null || Object.keys(value).length > 0;
466
- }
467
- return !0;
192
+ function defineTypedQuery(query) {
193
+ return query;
468
194
  }
469
195
  /**
470
- * Converts a string between different casing formats.
196
+ * Runs a branded query against the dataset, resolving a missing document to undefined.
471
197
  *
472
- * @param value - The string to convert.
473
- * @param format - The target casing format.
474
- * @returns The converted string.
198
+ * @param client - The Sanity client to query with.
199
+ * @param query - The branded query to run.
200
+ * @returns The result, or undefined when the query matched nothing.
475
201
  */
476
- function convertCase(value, format) {
477
- let words = value.replaceAll(/(?<lower>[a-z0-9])(?<upper>[A-Z])/gu, "$<lower> $<upper>").replaceAll(/[-_\s]+/gu, " ").trim().toLowerCase();
478
- switch (format) {
479
- case "kebab": return words.replaceAll(/\s+/gu, "-");
480
- case "snake": return words.replaceAll(/\s+/gu, "_");
481
- case "camel": return words.replaceAll(/\s+(?<character>.)/gu, (_match, character) => character.toUpperCase());
482
- case "pascal": return words.replaceAll(/(?:^|\s+)(?<character>.)/gu, (_match, character) => character.toUpperCase());
483
- case "title": return words.replaceAll(/\b\w/gu, (character) => character.toUpperCase());
484
- case "sentence": return words.replaceAll(/^(?<character>.)/gu, (character) => character.toUpperCase());
485
- default: return value;
486
- }
487
- }
488
- function CodePreview(t0) {
489
- let $ = c(3), { code, language } = t0;
490
- if (!isDefined(code)) return null;
491
- let t1;
492
- return $[0] !== code || $[1] !== language ? (t1 = /* @__PURE__ */ jsx(CodeContent, {
493
- code,
494
- language
495
- }), $[0] = code, $[1] = language, $[2] = t1) : t1 = $[2], t1;
496
- }
497
- function CodeIcon(props) {
498
- let $ = c(4), t0, t1;
499
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "m16 18 6-6-6-6" }), t1 = /* @__PURE__ */ jsx("path", { d: "m8 6-6 6 6 6" }), $[0] = t0, $[1] = t1) : (t0 = $[0], t1 = $[1]);
500
- let t2;
501
- return $[2] === props ? t2 = $[3] : (t2 = /* @__PURE__ */ jsxs("svg", {
502
- xmlns: "http://www.w3.org/2000/svg",
503
- width: 24,
504
- height: 24,
505
- viewBox: "0 0 24 24",
506
- fill: "none",
507
- stroke: "currentColor",
508
- strokeWidth: 2,
509
- strokeLinecap: "round",
510
- strokeLinejoin: "round",
511
- ...props,
512
- children: [t0, t1]
513
- }), $[2] = props, $[3] = t2), t2;
514
- }
515
- /** Type name of the code block. */
516
- const codeTypeName = "handbook.code", codeType = defineType({
517
- name: codeTypeName,
518
- type: "object",
519
- title: "Code",
520
- icon: createSanityIcon(CodeIcon),
521
- description: "Syntax-highlighted code block with language selection.",
522
- components: { preview: CodePreview },
523
- preview: { select: {
524
- code: "code",
525
- language: "language"
526
- } },
527
- fields: [defineField({
528
- name: "code",
529
- type: "text",
530
- description: "The source code to display."
531
- }), defineField({
532
- name: "language",
533
- type: "string",
534
- description: "Programming language used for syntax highlighting.",
535
- options: { list: [
536
- {
537
- title: "CSS",
538
- value: "css"
539
- },
540
- {
541
- title: "GROQ",
542
- value: "groq"
543
- },
544
- {
545
- title: "HTML",
546
- value: "html"
547
- },
548
- {
549
- title: "JavaScript",
550
- value: "javascript"
551
- },
552
- {
553
- title: "JSON",
554
- value: "json"
555
- },
556
- {
557
- title: "Plain Text",
558
- value: "text"
559
- },
560
- {
561
- title: "React",
562
- value: "tsx"
563
- },
564
- {
565
- title: "Shell",
566
- value: "shell"
567
- },
568
- {
569
- title: "TypeScript",
570
- value: "typescript"
571
- }
572
- ] }
573
- })]
574
- });
575
- function HorizontalRuleContent(t0) {
576
- let $ = c(8), props, style;
577
- $[0] === t0 ? (props = $[1], style = $[2]) : ({style, ...props} = t0, $[0] = t0, $[1] = props, $[2] = style);
578
- let t1;
579
- $[3] === style ? t1 = $[4] : (t1 = {
580
- border: "none",
581
- borderTop: "1px solid var(--card-border-color)",
582
- ...style
583
- }, $[3] = style, $[4] = t1);
584
- let t2;
585
- return $[5] !== props || $[6] !== t1 ? (t2 = /* @__PURE__ */ jsx("hr", {
586
- style: t1,
587
- ...props
588
- }), $[5] = props, $[6] = t1, $[7] = t2) : t2 = $[7], t2;
589
- }
590
- function HorizontalRulePreview(_props) {
591
- let $ = c(1), t0;
592
- return $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx(HorizontalRuleContent, { style: { marginBlock: 8 } }), $[0] = t0) : t0 = $[0], t0;
593
- }
594
- function SeparatorHorizontalIcon(props) {
595
- let $ = c(5), t0, t1, t2;
596
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "m16 16-4 4-4-4" }), t1 = /* @__PURE__ */ jsx("path", { d: "M3 12h18" }), t2 = /* @__PURE__ */ jsx("path", { d: "m8 8 4-4 4 4" }), $[0] = t0, $[1] = t1, $[2] = t2) : (t0 = $[0], t1 = $[1], t2 = $[2]);
597
- let t3;
598
- return $[3] === props ? t3 = $[4] : (t3 = /* @__PURE__ */ jsxs("svg", {
599
- xmlns: "http://www.w3.org/2000/svg",
600
- width: 24,
601
- height: 24,
602
- viewBox: "0 0 24 24",
603
- fill: "none",
604
- stroke: "currentColor",
605
- strokeWidth: 2,
606
- strokeLinecap: "round",
607
- strokeLinejoin: "round",
608
- ...props,
609
- children: [
610
- t0,
611
- t1,
612
- t2
613
- ]
614
- }), $[3] = props, $[4] = t3), t3;
615
- }
616
- /** Type name of the horizontal rule block. */
617
- const horizontalRuleTypeName = "handbook.horizontalRule", horizontalRuleType = defineType({
618
- name: horizontalRuleTypeName,
619
- type: "object",
620
- title: "Horizontal Rule",
621
- icon: createSanityIcon(SeparatorHorizontalIcon),
622
- description: "Visual divider between sections of content.",
623
- components: { preview: HorizontalRulePreview },
624
- preview: { prepare() {
625
- return { title: "Horizontal Rule" };
626
- } },
627
- fields: [defineField({
628
- name: "style",
629
- type: "string",
630
- description: "Reserved. A horizontal rule carries no authored content.",
631
- hidden: !0
632
- })]
633
- });
634
- function Caption(t0) {
635
- let $ = c(13), children, props, style;
636
- $[0] === t0 ? (children = $[1], props = $[2], style = $[3]) : ({children, style, ...props} = t0, $[0] = t0, $[1] = children, $[2] = props, $[3] = style);
637
- let t1;
638
- $[4] === style ? t1 = $[5] : (t1 = {
639
- marginBlockStart: 12,
640
- ...style
641
- }, $[4] = style, $[5] = t1);
642
- let t2;
643
- $[6] === Symbol.for("react.memo_cache_sentinel") ? (t2 = { fontStyle: "italic" }, $[6] = t2) : t2 = $[6];
644
- let t3;
645
- $[7] === children ? t3 = $[8] : (t3 = /* @__PURE__ */ jsx(Text, {
646
- size: 1,
647
- muted: !0,
648
- style: t2,
649
- children
650
- }), $[7] = children, $[8] = t3);
651
- let t4;
652
- return $[9] !== props || $[10] !== t1 || $[11] !== t3 ? (t4 = /* @__PURE__ */ jsx("div", {
653
- style: t1,
654
- ...props,
655
- children: t3
656
- }), $[9] = props, $[10] = t1, $[11] = t3, $[12] = t4) : t4 = $[12], t4;
657
- }
658
- function ImageContent(t0) {
659
- let $ = c(15), alt, caption, props, url;
660
- $[0] === t0 ? (alt = $[1], caption = $[2], props = $[3], url = $[4]) : ({url, alt, caption, ...props} = t0, $[0] = t0, $[1] = alt, $[2] = caption, $[3] = props, $[4] = url);
661
- let t1 = alt ?? "", t2;
662
- $[5] === Symbol.for("react.memo_cache_sentinel") ? (t2 = {
663
- display: "block",
664
- maxWidth: "100%",
665
- borderRadius: 4
666
- }, $[5] = t2) : t2 = $[5];
667
- let t3;
668
- $[6] !== t1 || $[7] !== url ? (t3 = /* @__PURE__ */ jsx("img", {
669
- src: url,
670
- alt: t1,
671
- style: t2
672
- }), $[6] = t1, $[7] = url, $[8] = t3) : t3 = $[8];
673
- let t4;
674
- $[9] === caption ? t4 = $[10] : (t4 = isDefined(caption) && /* @__PURE__ */ jsx(Caption, { children: caption }), $[9] = caption, $[10] = t4);
675
- let t5;
676
- return $[11] !== props || $[12] !== t3 || $[13] !== t4 ? (t5 = /* @__PURE__ */ jsxs("div", {
677
- ...props,
678
- children: [t3, t4]
679
- }), $[11] = props, $[12] = t3, $[13] = t4, $[14] = t5) : t5 = $[14], t5;
680
- }
681
- function ImagePreview(t0) {
682
- let $ = c(5), { url, alt, caption } = t0;
683
- if (!isDefined(url)) return null;
684
- let t1;
685
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t1 = { padding: 8 }, $[0] = t1) : t1 = $[0];
686
- let t2;
687
- return $[1] !== alt || $[2] !== caption || $[3] !== url ? (t2 = /* @__PURE__ */ jsx(ImageContent, {
688
- url,
689
- alt,
690
- caption,
691
- style: t1
692
- }), $[1] = alt, $[2] = caption, $[3] = url, $[4] = t2) : t2 = $[4], t2;
693
- }
694
- function ImageIcon(props) {
695
- let $ = c(5), t0, t1, t2;
696
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("rect", {
697
- width: "18",
698
- height: "18",
699
- x: "3",
700
- y: "3",
701
- rx: "2",
702
- ry: "2"
703
- }), t1 = /* @__PURE__ */ jsx("circle", {
704
- cx: "9",
705
- cy: "9",
706
- r: "2"
707
- }), t2 = /* @__PURE__ */ jsx("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" }), $[0] = t0, $[1] = t1, $[2] = t2) : (t0 = $[0], t1 = $[1], t2 = $[2]);
708
- let t3;
709
- return $[3] === props ? t3 = $[4] : (t3 = /* @__PURE__ */ jsxs("svg", {
710
- xmlns: "http://www.w3.org/2000/svg",
711
- width: 24,
712
- height: 24,
713
- viewBox: "0 0 24 24",
714
- fill: "none",
715
- stroke: "currentColor",
716
- strokeWidth: 2,
717
- strokeLinecap: "round",
718
- strokeLinejoin: "round",
719
- ...props,
720
- children: [
721
- t0,
722
- t1,
723
- t2
724
- ]
725
- }), $[3] = props, $[4] = t3), t3;
726
- }
727
- /** Type name of the image block. */
728
- const imageTypeName = "handbook.image", imageType = defineType({
729
- name: imageTypeName,
730
- type: "object",
731
- title: "Image",
732
- icon: createSanityIcon(ImageIcon),
733
- description: "Image with an optional caption and alternative text.",
734
- components: { preview: ImagePreview },
735
- preview: { select: {
736
- caption: "caption",
737
- alt: "alt",
738
- url: "asset.asset.url"
739
- } },
740
- fields: [
741
- defineField({
742
- name: "asset",
743
- title: "Image",
744
- type: "image",
745
- description: "Upload or select an image from the media library.",
746
- options: { hotspot: !0 }
747
- }),
748
- defineField({
749
- name: "caption",
750
- type: "string",
751
- description: "Caption text displayed below the image, such as a credit or a note."
752
- }),
753
- defineField({
754
- name: "alt",
755
- title: "Alternative Text",
756
- type: "string",
757
- description: "Describes what the image shows for people who cannot see it. Don't repeat the caption here."
758
- })
759
- ]
760
- });
761
- function VideoContent(t0) {
762
- let $ = c(16), caption, props, url;
763
- $[0] === t0 ? (caption = $[1], props = $[2], url = $[3]) : ({url, caption, ...props} = t0, $[0] = t0, $[1] = caption, $[2] = props, $[3] = url);
764
- let t1;
765
- $[4] === Symbol.for("react.memo_cache_sentinel") ? (t1 = {
766
- display: "block",
767
- maxWidth: "100%",
768
- borderRadius: 4,
769
- WebkitTransform: "translateZ(0)"
770
- }, $[4] = t1) : t1 = $[4];
771
- let t2 = caption ?? "Video", t3;
772
- $[5] === t2 ? t3 = $[6] : (t3 = /* @__PURE__ */ jsx("track", {
773
- kind: "captions",
774
- label: t2
775
- }), $[5] = t2, $[6] = t3);
776
- let t4;
777
- $[7] !== t3 || $[8] !== url ? (t4 = /* @__PURE__ */ jsx("video", {
778
- src: url,
779
- controls: !0,
780
- style: t1,
781
- children: t3
782
- }), $[7] = t3, $[8] = url, $[9] = t4) : t4 = $[9];
783
- let t5;
784
- $[10] === caption ? t5 = $[11] : (t5 = isDefined(caption) && /* @__PURE__ */ jsx(Caption, { children: caption }), $[10] = caption, $[11] = t5);
785
- let t6;
786
- return $[12] !== props || $[13] !== t4 || $[14] !== t5 ? (t6 = /* @__PURE__ */ jsxs("div", {
787
- ...props,
788
- children: [t4, t5]
789
- }), $[12] = props, $[13] = t4, $[14] = t5, $[15] = t6) : t6 = $[15], t6;
790
- }
791
- function VideoPreview(t0) {
792
- let $ = c(4), { url, caption } = t0;
793
- if (!isDefined(url)) return null;
794
- let t1;
795
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t1 = { padding: 8 }, $[0] = t1) : t1 = $[0];
796
- let t2;
797
- return $[1] !== caption || $[2] !== url ? (t2 = /* @__PURE__ */ jsx(VideoContent, {
798
- url,
799
- caption,
800
- style: t1
801
- }), $[1] = caption, $[2] = url, $[3] = t2) : t2 = $[3], t2;
802
- }
803
- function FilmIcon(props) {
804
- let $ = c(10), t0, t1, t2, t3, t4, t5, t6, t7;
805
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("rect", {
806
- x: "3",
807
- y: "3",
808
- width: "18",
809
- height: "18",
810
- rx: "2"
811
- }), t1 = /* @__PURE__ */ jsx("path", { d: "M7 3v18" }), t2 = /* @__PURE__ */ jsx("path", { d: "M3 7.5h4" }), t3 = /* @__PURE__ */ jsx("path", { d: "M3 12h18" }), t4 = /* @__PURE__ */ jsx("path", { d: "M3 16.5h4" }), t5 = /* @__PURE__ */ jsx("path", { d: "M17 3v18" }), t6 = /* @__PURE__ */ jsx("path", { d: "M17 7.5h4" }), t7 = /* @__PURE__ */ jsx("path", { d: "M17 16.5h4" }), $[0] = t0, $[1] = t1, $[2] = t2, $[3] = t3, $[4] = t4, $[5] = t5, $[6] = t6, $[7] = t7) : (t0 = $[0], t1 = $[1], t2 = $[2], t3 = $[3], t4 = $[4], t5 = $[5], t6 = $[6], t7 = $[7]);
812
- let t8;
813
- return $[8] === props ? t8 = $[9] : (t8 = /* @__PURE__ */ jsxs("svg", {
814
- xmlns: "http://www.w3.org/2000/svg",
815
- width: 24,
816
- height: 24,
817
- viewBox: "0 0 24 24",
818
- fill: "none",
819
- stroke: "currentColor",
820
- strokeWidth: 2,
821
- strokeLinecap: "round",
822
- strokeLinejoin: "round",
823
- ...props,
824
- children: [
825
- t0,
826
- t1,
827
- t2,
828
- t3,
829
- t4,
830
- t5,
831
- t6,
832
- t7
833
- ]
834
- }), $[8] = props, $[9] = t8), t8;
835
- }
836
- /** Type name of the video block. */
837
- const videoTypeName = "handbook.video", videoType = defineType({
838
- name: videoTypeName,
839
- type: "object",
840
- title: "Video",
841
- icon: createSanityIcon(FilmIcon),
842
- description: "Video with an optional caption.",
843
- components: { preview: VideoPreview },
844
- preview: { select: {
845
- caption: "caption",
846
- url: "asset.asset.url"
847
- } },
848
- fields: [defineField({
849
- name: "asset",
850
- title: "Video",
851
- type: "file",
852
- description: "Upload or select a video from the media library.",
853
- options: { accept: "video/*" }
854
- }), defineField({
855
- name: "caption",
856
- type: "string",
857
- description: "Caption text displayed below the video, such as a credit or a note."
858
- })]
859
- });
860
- /**
861
- * Creates the Portable Text content field for Handbook guides, offering the built-in blocks alongside
862
- * any a consumer registered.
863
- *
864
- * @param customBlocks - Custom block definitions registered by the consumer.
865
- * @returns A field definition for the guide content array.
866
- */
867
- function createGuideContentField(customBlocks = []) {
868
- return defineField({
869
- name: "content",
870
- type: "array",
871
- description: "Rich text with formatting, headings, lists, images, code blocks, and custom blocks.",
872
- of: [
873
- defineArrayMember({
874
- name: "block",
875
- type: "block",
876
- styles: [
877
- {
878
- title: "Paragraph",
879
- value: "normal",
880
- component: ParagraphStyle
881
- },
882
- {
883
- title: "Heading",
884
- value: "h2",
885
- component: HeadingStyle
886
- },
887
- {
888
- title: "Blockquote",
889
- value: "blockquote",
890
- component: BlockquoteStyle
891
- }
892
- ],
893
- lists: [{
894
- title: "Bullet",
895
- value: "bullet",
896
- component: ListItemStyle
897
- }, {
898
- title: "Number",
899
- value: "number",
900
- component: ListItemStyle
901
- }],
902
- marks: {
903
- decorators: [
904
- {
905
- title: "Bold",
906
- value: "strong"
907
- },
908
- {
909
- title: "Italic",
910
- value: "em"
911
- },
912
- {
913
- title: "Strikethrough",
914
- value: "strike-through"
915
- },
916
- {
917
- title: "Code",
918
- value: "code",
919
- component: CodeDecorator
920
- }
921
- ],
922
- annotations: [linkAnnotation]
923
- }
924
- }),
925
- defineArrayMember({
926
- name: imageTypeName,
927
- type: imageTypeName
928
- }),
929
- defineArrayMember({
930
- name: videoTypeName,
931
- type: videoTypeName
932
- }),
933
- defineArrayMember({
934
- name: codeTypeName,
935
- type: codeTypeName
936
- }),
937
- defineArrayMember({
938
- name: calloutTypeName,
939
- type: calloutTypeName
940
- }),
941
- defineArrayMember({
942
- name: horizontalRuleTypeName,
943
- type: horizontalRuleTypeName
944
- }),
945
- ...customBlocks.map((block) => defineArrayMember({
946
- name: block.schema.name,
947
- type: block.schema.name
948
- }))
949
- ]
950
- });
951
- }
952
- /** Document type name of an individual guide. */
953
- const guideTypeName = "handbook.guide";
954
- /**
955
- * Creates the document type a single guide is authored as, with its content field offering the
956
- * built-in blocks alongside any a consumer registered.
957
- *
958
- * @param customBlocks - Custom block definitions registered by the consumer.
959
- * @returns A document type definition for Handbook guides.
960
- */
961
- function createGuideType(customBlocks = []) {
962
- return defineType({
963
- name: guideTypeName,
964
- type: "document",
965
- title: "Handbook Guide",
966
- icon: createSanityIcon(BookOpenTextIcon),
967
- description: "Handbook page authored with rich text, images, and custom blocks.",
968
- preview: {
969
- select: {
970
- title: "title",
971
- description: "description"
972
- },
973
- prepare(selection) {
974
- let { title, description } = selection;
975
- return {
976
- title: title ?? "Untitled",
977
- subtitle: description
978
- };
979
- }
980
- },
981
- fields: [
982
- defineField({
983
- name: "title",
984
- type: "string",
985
- description: "Appears in the Handbook sidebar and as the guide heading.",
986
- validation: (rule) => rule.required()
987
- }),
988
- defineField({
989
- name: "description",
990
- type: "string",
991
- description: "Short introduction text displayed below the guide heading."
992
- }),
993
- createGuideContentField(customBlocks)
994
- ]
995
- });
996
- }
997
- function BookTextIcon(props) {
998
- let $ = c(5), t0, t1, t2;
999
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20" }), t1 = /* @__PURE__ */ jsx("path", { d: "M8 11h8" }), t2 = /* @__PURE__ */ jsx("path", { d: "M8 7h6" }), $[0] = t0, $[1] = t1, $[2] = t2) : (t0 = $[0], t1 = $[1], t2 = $[2]);
1000
- let t3;
1001
- return $[3] === props ? t3 = $[4] : (t3 = /* @__PURE__ */ jsxs("svg", {
1002
- xmlns: "http://www.w3.org/2000/svg",
1003
- width: 24,
1004
- height: 24,
1005
- viewBox: "0 0 24 24",
1006
- fill: "none",
1007
- stroke: "currentColor",
1008
- strokeWidth: 2,
1009
- strokeLinecap: "round",
1010
- strokeLinejoin: "round",
1011
- ...props,
1012
- children: [
1013
- t0,
1014
- t1,
1015
- t2
1016
- ]
1017
- }), $[3] = props, $[4] = t3), t3;
1018
- }
1019
- function ListPlusIcon(props) {
1020
- let $ = c(7), t0, t1, t2, t3, t4;
1021
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "M16 5H3" }), t1 = /* @__PURE__ */ jsx("path", { d: "M11 12H3" }), t2 = /* @__PURE__ */ jsx("path", { d: "M16 19H3" }), t3 = /* @__PURE__ */ jsx("path", { d: "M18 9v6" }), t4 = /* @__PURE__ */ jsx("path", { d: "M21 12h-6" }), $[0] = t0, $[1] = t1, $[2] = t2, $[3] = t3, $[4] = t4) : (t0 = $[0], t1 = $[1], t2 = $[2], t3 = $[3], t4 = $[4]);
1022
- let t5;
1023
- return $[5] === props ? t5 = $[6] : (t5 = /* @__PURE__ */ jsxs("svg", {
1024
- xmlns: "http://www.w3.org/2000/svg",
1025
- width: 24,
1026
- height: 24,
1027
- viewBox: "0 0 24 24",
1028
- fill: "none",
1029
- stroke: "currentColor",
1030
- strokeWidth: 2,
1031
- strokeLinecap: "round",
1032
- strokeLinejoin: "round",
1033
- ...props,
1034
- children: [
1035
- t0,
1036
- t1,
1037
- t2,
1038
- t3,
1039
- t4
1040
- ]
1041
- }), $[5] = props, $[6] = t5), t5;
1042
- }
1043
- /** Document type name of the Handbook singleton. */
1044
- const handbookTypeName = "handbook.handbook", handbookType = defineType({
1045
- name: handbookTypeName,
1046
- type: "document",
1047
- title: "Handbook",
1048
- icon: createSanityIcon(BookTextIcon),
1049
- description: "Defines the groups of guides shown in the Handbook sidebar, and the order they appear in.",
1050
- preview: { prepare() {
1051
- return { title: "Handbook" };
1052
- } },
1053
- fields: [defineField({
1054
- name: "groups",
1055
- type: "array",
1056
- description: "Ordered list of groups displayed in the Handbook sidebar. Each group contains a title and an ordered list of guide references.",
1057
- of: [defineArrayMember({
1058
- name: "group",
1059
- type: "object",
1060
- icon: createSanityIcon(ListPlusIcon),
1061
- description: "Named section of the Handbook sidebar holding an ordered list of guides.",
1062
- fields: [defineField({
1063
- name: "title",
1064
- type: "string",
1065
- description: "Heading displayed above this group of guides in the sidebar.",
1066
- validation: (rule) => rule.required()
1067
- }), defineField({
1068
- name: "guides",
1069
- type: "array",
1070
- description: "Ordered list of guides within this group. Drag to reorder.",
1071
- of: [defineArrayMember({
1072
- name: "guide",
1073
- type: "reference",
1074
- to: [{ type: guideTypeName }]
1075
- })]
1076
- })],
1077
- preview: {
1078
- select: {
1079
- title: "title",
1080
- guide0: "guides.0.title",
1081
- guide1: "guides.1.title",
1082
- guide2: "guides.2.title"
1083
- },
1084
- prepare(selection) {
1085
- let { title, guide0, guide1, guide2 } = selection, shown = [
1086
- guide0,
1087
- guide1,
1088
- guide2
1089
- ].filter((guide) => isDefined(guide)).slice(0, 2), hasMore = isDefined(guide2);
1090
- function formatSubtitle() {
1091
- return isDefined(shown) ? hasMore ? `${shown.join(", ")}, and others` : shown.join(" and ") : "No guides selected";
1092
- }
1093
- return {
1094
- title: title ?? "Group",
1095
- subtitle: formatSubtitle()
1096
- };
1097
- }
1098
- }
1099
- })]
1100
- })]
1101
- }), singletonTypes = /* @__PURE__ */ new Set([handbookTypeName]), documentTypes = /* @__PURE__ */ new Set([handbookTypeName, guideTypeName]), contentSpacing = {
1102
- section: 48,
1103
- paragraph: 16,
1104
- heading: 48,
1105
- media: 24,
1106
- callout: 32,
1107
- blockquote: 32,
1108
- list: 32,
1109
- nestedList: 12,
1110
- rule: 40
1111
- }, assetUrlFragment = "\"asset\": { \"url\": asset.asset->url }", guideFragment = `...@-> {
1112
- ...,
1113
- content[] { ..., ${`
1114
- _type == "${imageTypeName}" => { ..., ${assetUrlFragment} },
1115
- _type == "${videoTypeName}" => { ..., ${assetUrlFragment} }
1116
- `} }
1117
- }`;
1118
- /**
1119
- * Brands a GROQ query with the shape of the data it returns, so a fetch can infer its result type
1120
- * instead of being told it at every call site.
1121
- *
1122
- * @param query - The GROQ query string.
1123
- * @returns The query, typed to the given result shape.
1124
- */
1125
- function defineTypedQuery(query) {
1126
- return query;
1127
- }
1128
- /**
1129
- * Runs a branded query against the dataset, resolving a missing document to undefined.
1130
- *
1131
- * @param client - The Sanity client to query with.
1132
- * @param query - The branded query to run.
1133
- * @returns The result, or undefined when the query matched nothing.
1134
- */
1135
- async function fetchQuery(client, query) {
1136
- return await client.fetch(query) ?? void 0;
202
+ async function fetchQuery(client, query) {
203
+ return await client.fetch(query) ?? void 0;
1137
204
  }
1138
205
  /** Fetches the Handbook singleton with expanded guide references. */
1139
206
  const handbookQuery = defineTypedQuery(`
@@ -1181,18 +248,17 @@ const HandbookContext = createContext(void 0);
1181
248
  * Accesses the Handbook context for tab state and plugin configuration.
1182
249
  *
1183
250
  * @returns The resolved plugin configuration alongside the state the panes share.
1184
- * @throws {Error} If used outside the provider.
251
+ * @throws If used outside the provider.
1185
252
  */
1186
253
  function useHandbookContext() {
1187
254
  let handbookContext = useContext(HandbookContext);
1188
- if (!isDefined(handbookContext)) throw Error("useHandbookContext can only be used within <HandbookProvider>");
255
+ if (!isDefined(handbookContext)) throw Error(logger.format("Handbook context is only available inside the Handbook provider."));
1189
256
  return handbookContext;
1190
257
  }
1191
258
  /**
1192
259
  * Provides the tab state the sidebar and content panes share, alongside the plugin configuration and
1193
260
  * the handbook singleton fetched from the dataset.
1194
261
  *
1195
- * @param props - Configuration from the plugin, and the tool to provide it to.
1196
262
  * @returns The provider wrapping its children.
1197
263
  */
1198
264
  function HandbookProvider(t0) {
@@ -1373,7 +439,7 @@ function ContentPanel(t0) {
1373
439
  return $[28] !== t2 || $[29] !== t9 ? (t10 = /* @__PURE__ */ jsxs(Fragment, { children: [t2, t9] }), $[28] = t2, $[29] = t9, $[30] = t10) : t10 = $[30], t10;
1374
440
  }
1375
441
  function FieldHint(t0) {
1376
- let $ = c(33), children, icon, label, onClose, onOpen, open, props;
442
+ let $ = c(32), children, icon, label, onClose, onOpen, open, props;
1377
443
  $[0] === t0 ? (children = $[1], icon = $[2], label = $[3], onClose = $[4], onOpen = $[5], open = $[6], props = $[7]) : ({label, icon, open, children, onOpen, onClose, ...props} = t0, $[0] = t0, $[1] = children, $[2] = icon, $[3] = label, $[4] = onClose, $[5] = onOpen, $[6] = open, $[7] = props);
1378
444
  let buttonReference = useRef(null), popoverReference = useRef(null), t1;
1379
445
  $[8] === Symbol.for("react.memo_cache_sentinel") ? (t1 = () => [buttonReference.current, popoverReference.current], $[8] = t1) : t1 = $[8], useClickOutsideEvent(open ? onClose : void 0, t1);
@@ -1412,29 +478,19 @@ function FieldHint(t0) {
1412
478
  event_0.pointerType === "mouse" && onClose();
1413
479
  }, $[19] = onClose, $[20] = t8);
1414
480
  let t9;
1415
- $[21] === Symbol.for("react.memo_cache_sentinel") ? (t9 = {
1416
- display: "flex",
1417
- alignItems: "center",
1418
- padding: 2,
1419
- fontSize: 16,
1420
- color: "var(--card-icon-color)",
1421
- background: "none",
1422
- border: "none",
1423
- cursor: "pointer"
1424
- }, $[21] = t9) : t9 = $[21];
1425
- let t10;
1426
- $[22] !== icon || $[23] !== label || $[24] !== t6 || $[25] !== t7 || $[26] !== t8 ? (t10 = /* @__PURE__ */ jsx("button", {
481
+ $[21] !== icon || $[22] !== label || $[23] !== t6 || $[24] !== t7 || $[25] !== t8 ? (t9 = /* @__PURE__ */ jsx(Button, {
1427
482
  ref: buttonReference,
1428
483
  "aria-label": label,
1429
- type: "button",
484
+ fontSize: 2,
485
+ icon,
486
+ mode: "bleed",
487
+ padding: 1,
1430
488
  onClick: t6,
1431
489
  onPointerEnter: t7,
1432
- onPointerLeave: t8,
1433
- style: t9,
1434
- children: icon
1435
- }), $[22] = icon, $[23] = label, $[24] = t6, $[25] = t7, $[26] = t8, $[27] = t10) : t10 = $[27];
1436
- let t11;
1437
- return $[28] !== open || $[29] !== props || $[30] !== t10 || $[31] !== t5 ? (t11 = /* @__PURE__ */ jsx(Popover, {
490
+ onPointerLeave: t8
491
+ }), $[21] = icon, $[22] = label, $[23] = t6, $[24] = t7, $[25] = t8, $[26] = t9) : t9 = $[26];
492
+ let t10;
493
+ return $[27] !== open || $[28] !== props || $[29] !== t5 || $[30] !== t9 ? (t10 = /* @__PURE__ */ jsx(Popover, {
1438
494
  open,
1439
495
  placement: "top",
1440
496
  portal: !0,
@@ -1442,8 +498,78 @@ function FieldHint(t0) {
1442
498
  shadow: 2,
1443
499
  content: t5,
1444
500
  ...props,
1445
- children: t10
1446
- }), $[28] = open, $[29] = props, $[30] = t10, $[31] = t5, $[32] = t11) : t11 = $[32], t11;
501
+ children: t9
502
+ }), $[27] = open, $[28] = props, $[29] = t5, $[30] = t9, $[31] = t10) : t10 = $[31], t10;
503
+ }
504
+ function InfoIcon(props) {
505
+ let $ = c(5), t0, t1, t2;
506
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("circle", {
507
+ cx: "12",
508
+ cy: "12",
509
+ r: "10"
510
+ }), t1 = /* @__PURE__ */ jsx("path", { d: "M12 16v-4" }), t2 = /* @__PURE__ */ jsx("path", { d: "M12 8h.01" }), $[0] = t0, $[1] = t1, $[2] = t2) : (t0 = $[0], t1 = $[1], t2 = $[2]);
511
+ let t3;
512
+ return $[3] === props ? t3 = $[4] : (t3 = /* @__PURE__ */ jsxs("svg", {
513
+ xmlns: "http://www.w3.org/2000/svg",
514
+ width: 24,
515
+ height: 24,
516
+ viewBox: "0 0 24 24",
517
+ fill: "none",
518
+ stroke: "currentColor",
519
+ strokeWidth: 2,
520
+ strokeLinecap: "round",
521
+ strokeLinejoin: "round",
522
+ ...props,
523
+ children: [
524
+ t0,
525
+ t1,
526
+ t2
527
+ ]
528
+ }), $[3] = props, $[4] = t3), t3;
529
+ }
530
+ function LightbulbIcon(props) {
531
+ let $ = c(5), t0, t1, t2;
532
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5" }), t1 = /* @__PURE__ */ jsx("path", { d: "M9 18h6" }), t2 = /* @__PURE__ */ jsx("path", { d: "M10 22h4" }), $[0] = t0, $[1] = t1, $[2] = t2) : (t0 = $[0], t1 = $[1], t2 = $[2]);
533
+ let t3;
534
+ return $[3] === props ? t3 = $[4] : (t3 = /* @__PURE__ */ jsxs("svg", {
535
+ xmlns: "http://www.w3.org/2000/svg",
536
+ width: 24,
537
+ height: 24,
538
+ viewBox: "0 0 24 24",
539
+ fill: "none",
540
+ stroke: "currentColor",
541
+ strokeWidth: 2,
542
+ strokeLinecap: "round",
543
+ strokeLinejoin: "round",
544
+ ...props,
545
+ children: [
546
+ t0,
547
+ t1,
548
+ t2
549
+ ]
550
+ }), $[3] = props, $[4] = t3), t3;
551
+ }
552
+ function TriangleAlertIcon(props) {
553
+ let $ = c(5), t0, t1, t2;
554
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }), t1 = /* @__PURE__ */ jsx("path", { d: "M12 9v4" }), t2 = /* @__PURE__ */ jsx("path", { d: "M12 17h.01" }), $[0] = t0, $[1] = t1, $[2] = t2) : (t0 = $[0], t1 = $[1], t2 = $[2]);
555
+ let t3;
556
+ return $[3] === props ? t3 = $[4] : (t3 = /* @__PURE__ */ jsxs("svg", {
557
+ xmlns: "http://www.w3.org/2000/svg",
558
+ width: 24,
559
+ height: 24,
560
+ viewBox: "0 0 24 24",
561
+ fill: "none",
562
+ stroke: "currentColor",
563
+ strokeWidth: 2,
564
+ strokeLinecap: "round",
565
+ strokeLinejoin: "round",
566
+ ...props,
567
+ children: [
568
+ t0,
569
+ t1,
570
+ t2
571
+ ]
572
+ }), $[3] = props, $[4] = t3), t3;
1447
573
  }
1448
574
  /** Hint kinds a field can carry, in the order they are displayed. */
1449
575
  const hintKinds = [
@@ -1577,7 +703,7 @@ const opaqueTypes = /* @__PURE__ */ new Set([
1577
703
  * @returns True if the value is a compiled field.
1578
704
  */
1579
705
  function isCompiledField(value) {
1580
- return typeof value != "object" || !value || !("name" in value) || !("type" in value) ? !1 : typeof value.type == "object" && value.type !== null;
706
+ return !isRecord(value) || !("name" in value) || !("type" in value) ? !1 : isRecord(value.type);
1581
707
  }
1582
708
  /**
1583
709
  * Checks whether a value has a `fields` array property.
@@ -1586,7 +712,7 @@ function isCompiledField(value) {
1586
712
  * @returns True if the value contains a `fields` array.
1587
713
  */
1588
714
  function hasFieldsArray(value) {
1589
- return typeof value != "object" || !value || !("fields" in value) ? !1 : Array.isArray(value.fields);
715
+ return isRecord(value) && Array.isArray(value.fields);
1590
716
  }
1591
717
  /**
1592
718
  * Checks whether a value has an `of` array property.
@@ -1595,7 +721,7 @@ function hasFieldsArray(value) {
1595
721
  * @returns True if the value contains an `of` array.
1596
722
  */
1597
723
  function hasOfArray(value) {
1598
- return typeof value != "object" || !value || !("of" in value) ? !1 : Array.isArray(value.of);
724
+ return isRecord(value) && Array.isArray(value.of);
1599
725
  }
1600
726
  /**
1601
727
  * Extracts the type name a value declares, where it names one at all.
@@ -1604,7 +730,8 @@ function hasOfArray(value) {
1604
730
  * @returns The type name, or undefined when the value declares none.
1605
731
  */
1606
732
  function getTypeName(value) {
1607
- if (typeof value == "object" && value && "type" in value) return typeof value.type == "string" ? value.type : void 0;
733
+ let typeName = readPath(value, ["type"]);
734
+ return typeof typeName == "string" ? typeName : void 0;
1608
735
  }
1609
736
  /**
1610
737
  * Extracts the parent type name from a compiled schema type, if present.
@@ -1613,7 +740,8 @@ function getTypeName(value) {
1613
740
  * @returns The parent type name, or undefined when the type extends none.
1614
741
  */
1615
742
  function getParentTypeName(resolvedType) {
1616
- if (typeof resolvedType == "object" && resolvedType && "type" in resolvedType && typeof resolvedType.type == "object" && resolvedType.type !== null && "name" in resolvedType.type) return String(resolvedType.type.name);
743
+ let parentName = readPath(resolvedType, ["type", "name"]);
744
+ return isDefined(parentName) ? String(parentName) : void 0;
1617
745
  }
1618
746
  /**
1619
747
  * Normalises a compiled schema field into the shape the Handbook renders. Type names already seen are
@@ -1623,7 +751,7 @@ function getParentTypeName(resolvedType) {
1623
751
  * @param visited - Type names already seen in this normalisation chain.
1624
752
  * @returns The normalised field.
1625
753
  */
1626
- function normaliseField(field, visited = /* @__PURE__ */ new Set()) {
754
+ function normalizeField(field, visited = /* @__PURE__ */ new Set()) {
1627
755
  if (isCompiledField(field)) {
1628
756
  let typeName = field.type.name, result = {
1629
757
  name: field.name,
@@ -1634,7 +762,7 @@ function normaliseField(field, visited = /* @__PURE__ */ new Set()) {
1634
762
  };
1635
763
  if (!visited.has(typeName)) {
1636
764
  let next = !opaqueTypes.has(typeName) && typeName !== "object" && typeName !== "array" ? /* @__PURE__ */ new Set([...visited, typeName]) : visited, fieldSource = hasFieldsArray(field) ? field : field.type, ofSource = hasOfArray(field) ? field : field.type;
1637
- hasFieldsArray(fieldSource) && (result.fields = fieldSource.fields.map((subfield) => normaliseField(subfield, next))), hasOfArray(ofSource) && (result.of = ofSource.of.map((member) => normaliseField(member, next)));
765
+ hasFieldsArray(fieldSource) && (result.fields = fieldSource.fields.map((subfield) => normalizeField(subfield, next))), hasOfArray(ofSource) && (result.of = ofSource.of.map((member) => normalizeField(member, next)));
1638
766
  }
1639
767
  return result;
1640
768
  }
@@ -1646,32 +774,32 @@ function normaliseField(field, visited = /* @__PURE__ */ new Set()) {
1646
774
  *
1647
775
  * @param resolvedType - The compiled or normalised schema type.
1648
776
  * @param parentName - The opaque base type name.
1649
- * @returns The custom fields, or undefined when the type adds none.
777
+ * @returns The custom fields, or undefined when none of them holds a value.
1650
778
  */
1651
779
  function resolveCustomFields(resolvedType, parentName) {
1652
780
  if (!hasFieldsArray(resolvedType)) return;
1653
- let inherited = inheritedFieldNames[parentName], customFields = resolvedType.fields.map((field) => normaliseField(field)).filter((field) => !isDefined(inherited) || !inherited.has(field.name));
781
+ let inherited = inheritedFieldNames[parentName], customFields = resolvedType.fields.map((field) => normalizeField(field)).filter((field) => !isDefined(inherited) || !inherited.has(field.name));
1654
782
  return isDefined(customFields) ? customFields : void 0;
1655
783
  }
1656
784
  /**
1657
785
  * Normalises a list of raw field values into the shape the Handbook renders.
1658
786
  *
1659
787
  * @param items - Raw field values to normalise.
1660
- * @returns The normalised fields, or undefined when the list holds none.
788
+ * @returns The normalised fields, or undefined when none of them holds a value.
1661
789
  */
1662
- function resolveNormalisedFields(items) {
1663
- let normalised = items.map((item) => normaliseField(item));
1664
- return isDefined(normalised) ? normalised : void 0;
790
+ function resolveNormalizedFields(items) {
791
+ let normalized = items.map((item) => normalizeField(item));
792
+ return isDefined(normalized) ? normalized : void 0;
1665
793
  }
1666
794
  /**
1667
795
  * Normalises array members and filters out opaque types that have no meaningful subfields.
1668
796
  *
1669
797
  * @param members - Raw array member values to normalise.
1670
- * @returns The normalised non-opaque members, or undefined when none remain.
798
+ * @returns The normalised non-opaque members, or undefined when none of them holds a value.
1671
799
  */
1672
- function resolveNormalisedMembers(members) {
1673
- let normalised = members.map((member) => normaliseField(member)).filter((member) => !opaqueTypes.has(member.type));
1674
- return isDefined(normalised) ? normalised : void 0;
800
+ function resolveNormalizedMembers(members) {
801
+ let normalized = members.map((member) => normalizeField(member)).filter((member) => !opaqueTypes.has(member.type));
802
+ return isDefined(normalized) ? normalized : void 0;
1675
803
  }
1676
804
  /**
1677
805
  * Resolves the name of the type a value extends, reaching into the schema registry when the value
@@ -1700,21 +828,21 @@ function resolveParentName(value, schema) {
1700
828
  function resolveFields(value, schema) {
1701
829
  if (hasFieldsArray(value)) {
1702
830
  let parentName = resolveParentName(value, schema);
1703
- return isDefined(parentName) && opaqueTypes.has(parentName) ? resolveCustomFields(value, parentName) : resolveNormalisedFields(value.fields);
831
+ return isDefined(parentName) && opaqueTypes.has(parentName) ? resolveCustomFields(value, parentName) : resolveNormalizedFields(value.fields);
1704
832
  }
1705
833
  if (hasOfArray(value)) {
1706
834
  let members = value.of;
1707
835
  if (members.length === 1) {
1708
- let [member] = members, normalised = normaliseField(member);
1709
- if (opaqueTypes.has(normalised.type)) return;
1710
- if (hasFieldsArray(normalised)) {
1711
- let parentName = resolveParentName(normalised, schema);
1712
- return isDefined(parentName) && opaqueTypes.has(parentName) ? resolveCustomFields(normalised, parentName) : resolveNormalisedFields(normalised.fields);
836
+ let [member] = members, normalized = normalizeField(member);
837
+ if (opaqueTypes.has(normalized.type)) return;
838
+ if (hasFieldsArray(normalized)) {
839
+ let parentName = resolveParentName(normalized, schema);
840
+ return isDefined(parentName) && opaqueTypes.has(parentName) ? resolveCustomFields(normalized, parentName) : resolveNormalizedFields(normalized.fields);
1713
841
  }
1714
- let memberType = schema.get(normalised.type);
842
+ let memberType = schema.get(normalized.type);
1715
843
  if (isDefined(memberType)) return resolveFields(memberType, schema);
1716
844
  }
1717
- return resolveNormalisedMembers(members);
845
+ return resolveNormalizedMembers(members);
1718
846
  }
1719
847
  }
1720
848
  /**
@@ -1735,7 +863,7 @@ function getSubfields(field, schema) {
1735
863
  }
1736
864
  /** Shared empty ancestor set, so the default prop keeps a stable reference across renders. */
1737
865
  const noAncestors = /* @__PURE__ */ new Set();
1738
- function Field(t0) {
866
+ function DocumentedField(t0) {
1739
867
  let $ = c(59), field, props, t1;
1740
868
  $[0] === t0 ? (field = $[1], props = $[2], t1 = $[3]) : ({field, ancestors: t1, ...props} = t0, $[0] = t0, $[1] = field, $[2] = props, $[3] = t1);
1741
869
  let ancestors = t1 === void 0 ? noAncestors : t1, schema = useSchema(), { undocumentedFieldMessage } = useHandbookContext(), [expanded, setExpanded] = useState(!1), t2;
@@ -1865,7 +993,7 @@ function Field(t0) {
1865
993
  ]
1866
994
  })]
1867
995
  })
1868
- }), expanded && /* @__PURE__ */ jsx("div", {
996
+ }), expanded && /* @__PURE__ */ jsx(Box, {
1869
997
  style: {
1870
998
  marginTop: 16,
1871
999
  marginBottom: 8,
@@ -1874,7 +1002,7 @@ function Field(t0) {
1874
1002
  },
1875
1003
  children: /* @__PURE__ */ jsx(Stack, {
1876
1004
  gap: 5,
1877
- children: subfields.map((subfield) => /* @__PURE__ */ jsx(Field, {
1005
+ children: subfields.map((subfield) => /* @__PURE__ */ jsx(DocumentedField, {
1878
1006
  field: subfield,
1879
1007
  ancestors: /* @__PURE__ */ new Set([...ancestors, field.type])
1880
1008
  }, subfield.name))
@@ -1905,7 +1033,7 @@ function documentTypesSections(roles) {
1905
1033
  flexDirection: "column",
1906
1034
  gap: contentSpacing.section
1907
1035
  },
1908
- children: document.fields.map((field) => /* @__PURE__ */ jsx(Field, { field }, field.name))
1036
+ children: document.fields.map((field) => /* @__PURE__ */ jsx(DocumentedField, { field }, field.name))
1909
1037
  })
1910
1038
  }))
1911
1039
  }));
@@ -2019,11 +1147,10 @@ function DocumentTypesOverview() {
2019
1147
  align: "center",
2020
1148
  gap: 2,
2021
1149
  style: { marginLeft: "-4px" },
2022
- children: [isDefined(Icon) && /* @__PURE__ */ jsx("div", {
1150
+ children: [isDefined(Icon) && /* @__PURE__ */ jsx(Flex, {
1151
+ align: "center",
1152
+ justify: "center",
2023
1153
  style: {
2024
- display: "flex",
2025
- alignItems: "center",
2026
- justifyContent: "center",
2027
1154
  width: 25,
2028
1155
  height: 25,
2029
1156
  color: "var(--card-icon-color)"
@@ -2136,7 +1263,7 @@ function HowToUse() {
2136
1263
  /* @__PURE__ */ jsx(Stack, {
2137
1264
  gap: 3,
2138
1265
  marginTop: 2,
2139
- children: hintKinds.map(_temp$2)
1266
+ children: hintKinds.map(_temp$3)
2140
1267
  })
2141
1268
  ]
2142
1269
  }), $[5] = t5) : t5 = $[5];
@@ -2184,16 +1311,15 @@ function HowToUse() {
2184
1311
  ]
2185
1312
  }), $[7] = t7) : t7 = $[7], t7;
2186
1313
  }
2187
- function _temp$2(t0) {
1314
+ function _temp$3(t0) {
2188
1315
  let { name, icon: Icon } = t0;
2189
1316
  return /* @__PURE__ */ jsxs(Flex, {
2190
1317
  align: "center",
2191
1318
  gap: 3,
2192
- children: [/* @__PURE__ */ jsx("div", {
1319
+ children: [/* @__PURE__ */ jsx(Flex, {
1320
+ align: "center",
1321
+ flex: "none",
2193
1322
  style: {
2194
- display: "flex",
2195
- alignItems: "center",
2196
- flexShrink: 0,
2197
1323
  fontSize: "16px",
2198
1324
  color: "var(--card-icon-color)"
2199
1325
  },
@@ -2222,12 +1348,83 @@ function gettingStartedSections() {
2222
1348
  }, {
2223
1349
  id: "document-types",
2224
1350
  title: "Document Types",
2225
- description: "An overview of all document types, organised by role. Select a document type to view its fields, descriptions, and examples.",
1351
+ description: "An overview of all document types, organized by role. Select a document type to view its fields, descriptions, and examples.",
2226
1352
  icon: createSanityIcon(LayoutGridIcon),
2227
1353
  render: () => /* @__PURE__ */ jsx(DocumentTypesOverview, {})
2228
1354
  }]
2229
1355
  }];
2230
1356
  }
1357
+ /** Presentation for each callout variant. */
1358
+ const presentation = {
1359
+ tip: {
1360
+ icon: LightbulbIcon,
1361
+ tone: "positive"
1362
+ },
1363
+ info: {
1364
+ icon: InfoIcon,
1365
+ tone: "primary"
1366
+ },
1367
+ warning: {
1368
+ icon: TriangleAlertIcon,
1369
+ tone: "caution"
1370
+ }
1371
+ };
1372
+ function CalloutContent(t0) {
1373
+ let $ = c(17), children, props, variant;
1374
+ $[0] === t0 ? (children = $[1], props = $[2], variant = $[3]) : ({variant, children, ...props} = t0, $[0] = t0, $[1] = children, $[2] = props, $[3] = variant);
1375
+ let { icon: Icon, tone } = presentation[variant], t1;
1376
+ $[4] === Symbol.for("react.memo_cache_sentinel") ? (t1 = {
1377
+ marginTop: "-2px",
1378
+ fontSize: "16px",
1379
+ color: "var(--card-icon-color)"
1380
+ }, $[4] = t1) : t1 = $[4];
1381
+ let t2;
1382
+ $[5] === Icon ? t2 = $[6] : (t2 = /* @__PURE__ */ jsx(Box, {
1383
+ flex: "none",
1384
+ style: t1,
1385
+ children: /* @__PURE__ */ jsx(Icon, { ...defaultIconProps })
1386
+ }), $[5] = Icon, $[6] = t2);
1387
+ let t3;
1388
+ $[7] === Symbol.for("react.memo_cache_sentinel") ? (t3 = { color: "var(--card-icon-color)" }, $[7] = t3) : t3 = $[7];
1389
+ let t4;
1390
+ $[8] === children ? t4 = $[9] : (t4 = /* @__PURE__ */ jsx(Text, {
1391
+ size: 1,
1392
+ style: t3,
1393
+ children
1394
+ }), $[8] = children, $[9] = t4);
1395
+ let t5;
1396
+ $[10] !== t2 || $[11] !== t4 ? (t5 = /* @__PURE__ */ jsxs(Flex, {
1397
+ align: "flex-start",
1398
+ gap: 3,
1399
+ children: [t2, t4]
1400
+ }), $[10] = t2, $[11] = t4, $[12] = t5) : t5 = $[12];
1401
+ let t6;
1402
+ return $[13] !== props || $[14] !== t5 || $[15] !== tone ? (t6 = /* @__PURE__ */ jsx(Card, {
1403
+ padding: 4,
1404
+ radius: 2,
1405
+ tone,
1406
+ ...props,
1407
+ children: t5
1408
+ }), $[13] = props, $[14] = t5, $[15] = tone, $[16] = t6) : t6 = $[16], t6;
1409
+ }
1410
+ function PortableCode(t0) {
1411
+ let $ = c(8), props, style;
1412
+ $[0] === t0 ? (props = $[1], style = $[2]) : ({style, ...props} = t0, $[0] = t0, $[1] = props, $[2] = style);
1413
+ let t1;
1414
+ $[3] === style ? t1 = $[4] : (t1 = {
1415
+ paddingBlock: 2,
1416
+ paddingInline: 4,
1417
+ fontSize: "0.875em",
1418
+ backgroundColor: "var(--card-code-bg-color)",
1419
+ borderRadius: 2,
1420
+ ...style
1421
+ }, $[3] = style, $[4] = t1);
1422
+ let t2;
1423
+ return $[5] !== props || $[6] !== t1 ? (t2 = /* @__PURE__ */ jsx("code", {
1424
+ style: t1,
1425
+ ...props
1426
+ }), $[5] = props, $[6] = t1, $[7] = t2) : t2 = $[7], t2;
1427
+ }
2231
1428
  function PortableLink(t0) {
2232
1429
  let $ = c(10), children, props, style;
2233
1430
  $[0] === t0 ? (children = $[1], props = $[2], style = $[3]) : ({children, style, ...props} = t0, $[0] = t0, $[1] = children, $[2] = props, $[3] = style);
@@ -2277,6 +1474,30 @@ function CalloutBlock(t0) {
2277
1474
  children: t2
2278
1475
  }), $[8] = props, $[9] = t1, $[10] = t2, $[11] = value.variant, $[12] = t3) : t3 = $[12], t3;
2279
1476
  }
1477
+ function CodeContent(t0) {
1478
+ let $ = c(14), code, language, props, style;
1479
+ $[0] === t0 ? (code = $[1], language = $[2], props = $[3], style = $[4]) : ({code, language, style, ...props} = t0, $[0] = t0, $[1] = code, $[2] = language, $[3] = props, $[4] = style);
1480
+ let t1;
1481
+ $[5] === style ? t1 = $[6] : (t1 = {
1482
+ overflowX: "auto",
1483
+ ...style
1484
+ }, $[5] = style, $[6] = t1);
1485
+ let t2;
1486
+ $[7] !== code || $[8] !== language ? (t2 = /* @__PURE__ */ jsx(Code, {
1487
+ size: 1,
1488
+ language,
1489
+ children: code
1490
+ }), $[7] = code, $[8] = language, $[9] = t2) : t2 = $[9];
1491
+ let t3;
1492
+ return $[10] !== props || $[11] !== t1 || $[12] !== t2 ? (t3 = /* @__PURE__ */ jsx(Card, {
1493
+ padding: 4,
1494
+ radius: 2,
1495
+ tone: "transparent",
1496
+ style: t1,
1497
+ ...props,
1498
+ children: t2
1499
+ }), $[10] = props, $[11] = t1, $[12] = t2, $[13] = t3) : t3 = $[13], t3;
1500
+ }
2280
1501
  function CodeBlock(t0) {
2281
1502
  let $ = c(11), props, style, value;
2282
1503
  if ($[0] === t0 ? (props = $[1], style = $[2], value = $[3]) : ({value, style, ...props} = t0, $[0] = t0, $[1] = props, $[2] = style, $[3] = value), !isDefined(value.code)) return null;
@@ -2293,6 +1514,21 @@ function CodeBlock(t0) {
2293
1514
  ...props
2294
1515
  }), $[6] = props, $[7] = t1, $[8] = value.code, $[9] = value.language, $[10] = t2) : t2 = $[10], t2;
2295
1516
  }
1517
+ function HorizontalRuleContent(t0) {
1518
+ let $ = c(8), props, style;
1519
+ $[0] === t0 ? (props = $[1], style = $[2]) : ({style, ...props} = t0, $[0] = t0, $[1] = props, $[2] = style);
1520
+ let t1;
1521
+ $[3] === style ? t1 = $[4] : (t1 = {
1522
+ border: "none",
1523
+ borderTop: "1px solid var(--card-border-color)",
1524
+ ...style
1525
+ }, $[3] = style, $[4] = t1);
1526
+ let t2;
1527
+ return $[5] !== props || $[6] !== t1 ? (t2 = /* @__PURE__ */ jsx("hr", {
1528
+ style: t1,
1529
+ ...props
1530
+ }), $[5] = props, $[6] = t1, $[7] = t2) : t2 = $[7], t2;
1531
+ }
2296
1532
  function HorizontalRuleBlock(t0) {
2297
1533
  let $ = c(8), props, style;
2298
1534
  if ($[0] !== t0) {
@@ -2310,6 +1546,48 @@ function HorizontalRuleBlock(t0) {
2310
1546
  ...props
2311
1547
  }), $[5] = props, $[6] = t1, $[7] = t2) : t2 = $[7], t2;
2312
1548
  }
1549
+ function Caption(t0) {
1550
+ let $ = c(9), children, props;
1551
+ $[0] === t0 ? (children = $[1], props = $[2]) : ({children, ...props} = t0, $[0] = t0, $[1] = children, $[2] = props);
1552
+ let t1;
1553
+ $[3] === Symbol.for("react.memo_cache_sentinel") ? (t1 = { fontStyle: "italic" }, $[3] = t1) : t1 = $[3];
1554
+ let t2;
1555
+ $[4] === children ? t2 = $[5] : (t2 = /* @__PURE__ */ jsx(Text, {
1556
+ size: 1,
1557
+ muted: !0,
1558
+ style: t1,
1559
+ children
1560
+ }), $[4] = children, $[5] = t2);
1561
+ let t3;
1562
+ return $[6] !== props || $[7] !== t2 ? (t3 = /* @__PURE__ */ jsx(Box, {
1563
+ marginTop: 3,
1564
+ ...props,
1565
+ children: t2
1566
+ }), $[6] = props, $[7] = t2, $[8] = t3) : t3 = $[8], t3;
1567
+ }
1568
+ function ImageContent(t0) {
1569
+ let $ = c(15), alt, caption, props, url;
1570
+ $[0] === t0 ? (alt = $[1], caption = $[2], props = $[3], url = $[4]) : ({url, alt, caption, ...props} = t0, $[0] = t0, $[1] = alt, $[2] = caption, $[3] = props, $[4] = url);
1571
+ let t1 = alt ?? "", t2;
1572
+ $[5] === Symbol.for("react.memo_cache_sentinel") ? (t2 = {
1573
+ display: "block",
1574
+ maxWidth: "100%",
1575
+ borderRadius: 4
1576
+ }, $[5] = t2) : t2 = $[5];
1577
+ let t3;
1578
+ $[6] !== t1 || $[7] !== url ? (t3 = /* @__PURE__ */ jsx("img", {
1579
+ src: url,
1580
+ alt: t1,
1581
+ style: t2
1582
+ }), $[6] = t1, $[7] = url, $[8] = t3) : t3 = $[8];
1583
+ let t4;
1584
+ $[9] === caption ? t4 = $[10] : (t4 = isDefined(caption) && /* @__PURE__ */ jsx(Caption, { children: caption }), $[9] = caption, $[10] = t4);
1585
+ let t5;
1586
+ return $[11] !== props || $[12] !== t3 || $[13] !== t4 ? (t5 = /* @__PURE__ */ jsxs("div", {
1587
+ ...props,
1588
+ children: [t3, t4]
1589
+ }), $[11] = props, $[12] = t3, $[13] = t4, $[14] = t5) : t5 = $[14], t5;
1590
+ }
2313
1591
  function ImageBlock(t0) {
2314
1592
  let $ = c(12), props, style, value;
2315
1593
  if ($[0] === t0 ? (props = $[1], style = $[2], value = $[3]) : ({value, style, ...props} = t0, $[0] = t0, $[1] = props, $[2] = style, $[3] = value), !isDefined(value.asset?.url)) return null;
@@ -2327,6 +1605,36 @@ function ImageBlock(t0) {
2327
1605
  ...props
2328
1606
  }), $[6] = props, $[7] = t1, $[8] = value.alt, $[9] = value.asset.url, $[10] = value.caption, $[11] = t2) : t2 = $[11], t2;
2329
1607
  }
1608
+ function VideoContent(t0) {
1609
+ let $ = c(16), caption, props, url;
1610
+ $[0] === t0 ? (caption = $[1], props = $[2], url = $[3]) : ({url, caption, ...props} = t0, $[0] = t0, $[1] = caption, $[2] = props, $[3] = url);
1611
+ let t1;
1612
+ $[4] === Symbol.for("react.memo_cache_sentinel") ? (t1 = {
1613
+ display: "block",
1614
+ maxWidth: "100%",
1615
+ borderRadius: 4,
1616
+ WebkitTransform: "translateZ(0)"
1617
+ }, $[4] = t1) : t1 = $[4];
1618
+ let t2 = caption ?? "Video", t3;
1619
+ $[5] === t2 ? t3 = $[6] : (t3 = /* @__PURE__ */ jsx("track", {
1620
+ kind: "captions",
1621
+ label: t2
1622
+ }), $[5] = t2, $[6] = t3);
1623
+ let t4;
1624
+ $[7] !== t3 || $[8] !== url ? (t4 = /* @__PURE__ */ jsx("video", {
1625
+ src: url,
1626
+ controls: !0,
1627
+ style: t1,
1628
+ children: t3
1629
+ }), $[7] = t3, $[8] = url, $[9] = t4) : t4 = $[9];
1630
+ let t5;
1631
+ $[10] === caption ? t5 = $[11] : (t5 = isDefined(caption) && /* @__PURE__ */ jsx(Caption, { children: caption }), $[10] = caption, $[11] = t5);
1632
+ let t6;
1633
+ return $[12] !== props || $[13] !== t4 || $[14] !== t5 ? (t6 = /* @__PURE__ */ jsxs("div", {
1634
+ ...props,
1635
+ children: [t4, t5]
1636
+ }), $[12] = props, $[13] = t4, $[14] = t5, $[15] = t6) : t6 = $[15], t6;
1637
+ }
2330
1638
  function VideoBlock(t0) {
2331
1639
  let $ = c(11), props, style, value;
2332
1640
  if ($[0] === t0 ? (props = $[1], style = $[2], value = $[3]) : ({value, style, ...props} = t0, $[0] = t0, $[1] = props, $[2] = style, $[3] = value), !isDefined(value.asset?.url)) return null;
@@ -2343,6 +1651,41 @@ function VideoBlock(t0) {
2343
1651
  ...props
2344
1652
  }), $[6] = props, $[7] = t1, $[8] = value.asset.url, $[9] = value.caption, $[10] = t2) : t2 = $[10], t2;
2345
1653
  }
1654
+ function PortableBlockquote(t0) {
1655
+ let $ = c(15), children, muted, props, style;
1656
+ $[0] === t0 ? (children = $[1], muted = $[2], props = $[3], style = $[4]) : ({muted, children, style, ...props} = t0, $[0] = t0, $[1] = children, $[2] = muted, $[3] = props, $[4] = style);
1657
+ let t1;
1658
+ $[5] === style ? t1 = $[6] : (t1 = {
1659
+ borderLeft: "2px solid var(--card-border-color)",
1660
+ ...style
1661
+ }, $[5] = style, $[6] = t1);
1662
+ let t2;
1663
+ $[7] === Symbol.for("react.memo_cache_sentinel") ? (t2 = { fontStyle: "italic" }, $[7] = t2) : t2 = $[7];
1664
+ let t3;
1665
+ $[8] !== children || $[9] !== muted ? (t3 = /* @__PURE__ */ jsx(Text, {
1666
+ size: 1,
1667
+ muted,
1668
+ style: t2,
1669
+ children
1670
+ }), $[8] = children, $[9] = muted, $[10] = t3) : t3 = $[10];
1671
+ let t4;
1672
+ return $[11] !== props || $[12] !== t1 || $[13] !== t3 ? (t4 = /* @__PURE__ */ jsx(Box, {
1673
+ paddingY: 1,
1674
+ paddingLeft: 3,
1675
+ style: t1,
1676
+ ...props,
1677
+ children: t3
1678
+ }), $[11] = props, $[12] = t1, $[13] = t3, $[14] = t4) : t4 = $[14], t4;
1679
+ }
1680
+ function PortableHeading(props) {
1681
+ let $ = c(2), t0;
1682
+ return $[0] === props ? t0 = $[1] : (t0 = /* @__PURE__ */ jsx(Text, {
1683
+ as: "h2",
1684
+ size: 1,
1685
+ weight: "medium",
1686
+ ...props
1687
+ }), $[0] = props, $[1] = t0), t0;
1688
+ }
2346
1689
  function PortableList(t0) {
2347
1690
  let $ = c(12), props, style, t1;
2348
1691
  $[0] === t0 ? (props = $[1], style = $[2], t1 = $[3]) : ({ordered: t1, style, ...props} = t0, $[0] = t0, $[1] = props, $[2] = style, $[3] = t1);
@@ -2369,6 +1712,13 @@ function PortableList(t0) {
2369
1712
  ...props
2370
1713
  }), $[9] = listStyle, $[10] = props, $[11] = t3) : t3 = $[11], t3;
2371
1714
  }
1715
+ function PortableParagraph(props) {
1716
+ let $ = c(2), t0;
1717
+ return $[0] === props ? t0 = $[1] : (t0 = /* @__PURE__ */ jsx(Text, {
1718
+ size: 1,
1719
+ ...props
1720
+ }), $[0] = props, $[1] = t0), t0;
1721
+ }
2372
1722
  /**
2373
1723
  * Resolves the space around a list, which tightens once the list is nested inside another.
2374
1724
  *
@@ -2476,8 +1826,33 @@ function PortableText$1(t0) {
2476
1826
  let t8;
2477
1827
  return $[15] !== props || $[16] !== t7 ? (t8 = /* @__PURE__ */ jsx("div", {
2478
1828
  ...props,
2479
- children: t7
2480
- }), $[15] = props, $[16] = t7, $[17] = t8) : t8 = $[17], t8;
1829
+ children: t7
1830
+ }), $[15] = props, $[16] = t7, $[17] = t8) : t8 = $[17], t8;
1831
+ }
1832
+ function BookOpenTextIcon(props) {
1833
+ let $ = c(8), t0, t1, t2, t3, t4, t5;
1834
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "M12 7v14" }), t1 = /* @__PURE__ */ jsx("path", { d: "M16 12h2" }), t2 = /* @__PURE__ */ jsx("path", { d: "M16 8h2" }), t3 = /* @__PURE__ */ jsx("path", { d: "M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z" }), t4 = /* @__PURE__ */ jsx("path", { d: "M6 12h2" }), t5 = /* @__PURE__ */ jsx("path", { d: "M6 8h2" }), $[0] = t0, $[1] = t1, $[2] = t2, $[3] = t3, $[4] = t4, $[5] = t5) : (t0 = $[0], t1 = $[1], t2 = $[2], t3 = $[3], t4 = $[4], t5 = $[5]);
1835
+ let t6;
1836
+ return $[6] === props ? t6 = $[7] : (t6 = /* @__PURE__ */ jsxs("svg", {
1837
+ xmlns: "http://www.w3.org/2000/svg",
1838
+ width: 24,
1839
+ height: 24,
1840
+ viewBox: "0 0 24 24",
1841
+ fill: "none",
1842
+ stroke: "currentColor",
1843
+ strokeWidth: 2,
1844
+ strokeLinecap: "round",
1845
+ strokeLinejoin: "round",
1846
+ ...props,
1847
+ children: [
1848
+ t0,
1849
+ t1,
1850
+ t2,
1851
+ t3,
1852
+ t4,
1853
+ t5
1854
+ ]
1855
+ }), $[6] = props, $[7] = t6), t6;
2481
1856
  }
2482
1857
  /**
2483
1858
  * Builds a section for each guide group authored in the dataset.
@@ -2518,7 +1893,7 @@ function Content(props) {
2518
1893
  let { id } = t6;
2519
1894
  return id === activeTab;
2520
1895
  }, $[9] = activeTab, $[10] = t5);
2521
- let entry = sections.flatMap(_temp$1).find(t5);
1896
+ let entry = sections.flatMap(_temp$2).find(t5);
2522
1897
  T0 = Pane, t0 = "handbook-content", t1 = 2.5, t2 = 320, t3 = props, t4 = isDefined(entry) && /* @__PURE__ */ jsx(ContentPanel, {
2523
1898
  id: entry.id,
2524
1899
  title: entry.title,
@@ -2535,7 +1910,7 @@ function Content(props) {
2535
1910
  children: t4
2536
1911
  }), $[11] = T0, $[12] = t0, $[13] = t1, $[14] = t2, $[15] = t3, $[16] = t4, $[17] = t5) : t5 = $[17], t5;
2537
1912
  }
2538
- function _temp$1(section) {
1913
+ function _temp$2(section) {
2539
1914
  return section.entries;
2540
1915
  }
2541
1916
  function SidebarHeading(t0) {
@@ -2547,209 +1922,886 @@ function SidebarHeading(t0) {
2547
1922
  outline: "none"
2548
1923
  }, $[3] = t1) : t1 = $[3];
2549
1924
  let t2;
2550
- $[4] === title ? t2 = $[5] : (t2 = /* @__PURE__ */ jsx(Card, {
2551
- padding: 2,
2552
- children: /* @__PURE__ */ jsx(Text, {
2553
- size: 1,
2554
- muted: !0,
2555
- textOverflow: "ellipsis",
2556
- weight: "semibold",
2557
- style: t1,
2558
- children: title
2559
- })
2560
- }), $[4] = title, $[5] = t2);
2561
- let t3;
2562
- return $[6] !== props || $[7] !== t2 ? (t3 = /* @__PURE__ */ jsx(Box, {
2563
- paddingY: 2,
1925
+ $[4] === title ? t2 = $[5] : (t2 = /* @__PURE__ */ jsx(Card, {
1926
+ padding: 2,
1927
+ children: /* @__PURE__ */ jsx(Text, {
1928
+ size: 1,
1929
+ muted: !0,
1930
+ textOverflow: "ellipsis",
1931
+ weight: "semibold",
1932
+ style: t1,
1933
+ children: title
1934
+ })
1935
+ }), $[4] = title, $[5] = t2);
1936
+ let t3;
1937
+ return $[6] !== props || $[7] !== t2 ? (t3 = /* @__PURE__ */ jsx(Box, {
1938
+ paddingY: 2,
1939
+ ...props,
1940
+ children: t2
1941
+ }), $[6] = props, $[7] = t2, $[8] = t3) : t3 = $[8], t3;
1942
+ }
1943
+ function SidebarTab(t0) {
1944
+ let $ = c(25), Icon, id, label, props, style;
1945
+ $[0] === t0 ? (Icon = $[1], id = $[2], label = $[3], props = $[4], style = $[5]) : ({id, label, icon: Icon, style, ...props} = t0, $[0] = t0, $[1] = Icon, $[2] = id, $[3] = label, $[4] = props, $[5] = style);
1946
+ let { activeTab, setActiveTab, setSidebarExpanded } = useHandbookContext(), selected = activeTab === id, t1;
1947
+ $[6] !== id || $[7] !== setActiveTab || $[8] !== setSidebarExpanded ? (t1 = () => {
1948
+ setActiveTab(id), setSidebarExpanded(!1);
1949
+ }, $[6] = id, $[7] = setActiveTab, $[8] = setSidebarExpanded, $[9] = t1) : t1 = $[9];
1950
+ let t2;
1951
+ $[10] === style ? t2 = $[11] : (t2 = {
1952
+ cursor: "pointer",
1953
+ ...style
1954
+ }, $[10] = style, $[11] = t2);
1955
+ let t3 = `panel-${id}`, t4;
1956
+ $[12] === Symbol.for("react.memo_cache_sentinel") ? (t4 = { opacity: .5 }, $[12] = t4) : t4 = $[12];
1957
+ let t5;
1958
+ $[13] === Symbol.for("react.memo_cache_sentinel") ? (t5 = /* @__PURE__ */ jsx(Box, {
1959
+ style: t4,
1960
+ children: /* @__PURE__ */ jsx(Text, {
1961
+ muted: !0,
1962
+ size: 1,
1963
+ children: /* @__PURE__ */ jsx(ChevronRightIcon, {})
1964
+ })
1965
+ }), $[13] = t5) : t5 = $[13];
1966
+ let t6;
1967
+ $[14] !== Icon || $[15] !== label ? (t6 = /* @__PURE__ */ jsx(SanityDefaultPreview, {
1968
+ status: t5,
1969
+ icon: Icon,
1970
+ layout: "compact",
1971
+ title: label
1972
+ }), $[14] = Icon, $[15] = label, $[16] = t6) : t6 = $[16];
1973
+ let t7;
1974
+ return $[17] !== id || $[18] !== props || $[19] !== selected || $[20] !== t1 || $[21] !== t2 || $[22] !== t3 || $[23] !== t6 ? (t7 = /* @__PURE__ */ jsx(PreviewCard, {
1975
+ id,
1976
+ as: "button",
1977
+ "data-as": "button",
1978
+ selected,
1979
+ marginBottom: 1,
1980
+ radius: 2,
1981
+ sizing: "border",
1982
+ tabIndex: -1,
1983
+ tone: "inherit",
1984
+ onClick: t1,
1985
+ style: t2,
1986
+ "aria-controls": t3,
1987
+ __unstable_focusRing: !0,
1988
+ ...props,
1989
+ children: t6
1990
+ }), $[17] = id, $[18] = props, $[19] = selected, $[20] = t1, $[21] = t2, $[22] = t3, $[23] = t6, $[24] = t7) : t7 = $[24], t7;
1991
+ }
1992
+ function renderItem(item) {
1993
+ return item.type === "heading" ? /* @__PURE__ */ jsx(SidebarHeading, { title: item.title }) : /* @__PURE__ */ jsx(SidebarTab, {
1994
+ id: item.id,
1995
+ label: item.label,
1996
+ icon: item.icon
1997
+ });
1998
+ }
1999
+ function Sidebar(props) {
2000
+ let $ = c(14), { sidebarTitle } = useHandbookContext(), sections = useSections(), t0;
2001
+ $[0] === sections ? t0 = $[1] : (t0 = sections.flatMap(_temp2$1), $[0] = sections, $[1] = t0);
2002
+ let items = t0, t1;
2003
+ $[2] === items ? t1 = $[3] : (t1 = function getItemDisabled(virtualIndex) {
2004
+ return items[virtualIndex]?.type === "heading";
2005
+ }, $[2] = items, $[3] = t1);
2006
+ let getItemDisabled = t1, t2;
2007
+ $[4] === sidebarTitle ? t2 = $[5] : (t2 = /* @__PURE__ */ jsx(PaneHeader, { title: sidebarTitle }), $[4] = sidebarTitle, $[5] = t2);
2008
+ let t3;
2009
+ $[6] !== getItemDisabled || $[7] !== items || $[8] !== sidebarTitle ? (t3 = /* @__PURE__ */ jsx(PaneContent, {
2010
+ overflow: "auto",
2011
+ children: /* @__PURE__ */ jsx(CommandList, {
2012
+ activeItemDataAttr: "data-hovered",
2013
+ ariaLabel: sidebarTitle,
2014
+ canReceiveFocus: !0,
2015
+ getItemDisabled,
2016
+ itemHeight: 37,
2017
+ items,
2018
+ onlyShowSelectionWhenActive: !0,
2019
+ paddingBottom: 1,
2020
+ paddingX: 3,
2021
+ renderItem,
2022
+ wrapAround: !1
2023
+ })
2024
+ }), $[6] = getItemDisabled, $[7] = items, $[8] = sidebarTitle, $[9] = t3) : t3 = $[9];
2025
+ let t4;
2026
+ return $[10] !== props || $[11] !== t2 || $[12] !== t3 ? (t4 = /* @__PURE__ */ jsxs(Pane, {
2027
+ id: "handbook-sidebar",
2028
+ currentMaxWidth: 350,
2029
+ minWidth: 320,
2030
+ maxWidth: 640,
2031
+ ...props,
2032
+ children: [t2, t3]
2033
+ }), $[10] = props, $[11] = t2, $[12] = t3, $[13] = t4) : t4 = $[13], t4;
2034
+ }
2035
+ function _temp2$1(t0) {
2036
+ let { title, entries } = t0;
2037
+ return [{
2038
+ type: "heading",
2039
+ title
2040
+ }, ...entries.map(_temp$1)];
2041
+ }
2042
+ function _temp$1(entry) {
2043
+ return {
2044
+ type: "tab",
2045
+ id: entry.id,
2046
+ label: entry.title,
2047
+ icon: entry.icon
2048
+ };
2049
+ }
2050
+ function Panes() {
2051
+ let $ = c(10), { activeTab, sidebarExpanded } = useHandbookContext(), paneLayout = useContext(PaneLayoutContext), t0;
2052
+ $[0] === activeTab ? t0 = $[1] : (t0 = isDefined(activeTab), $[0] = activeTab, $[1] = t0);
2053
+ let hasContent = t0;
2054
+ if (paneLayout?.collapsed === !0) {
2055
+ let t1;
2056
+ return $[2] !== hasContent || $[3] !== sidebarExpanded ? (t1 = jsx(sidebarExpanded || !hasContent ? Sidebar : Content, {}), $[2] = hasContent, $[3] = sidebarExpanded, $[4] = t1) : t1 = $[4], t1;
2057
+ }
2058
+ let t1;
2059
+ $[5] === Symbol.for("react.memo_cache_sentinel") ? (t1 = /* @__PURE__ */ jsx(Sidebar, {}), $[5] = t1) : t1 = $[5];
2060
+ let t2;
2061
+ $[6] === hasContent ? t2 = $[7] : (t2 = hasContent && /* @__PURE__ */ jsx(Content, {}), $[6] = hasContent, $[7] = t2);
2062
+ let t3;
2063
+ return $[8] === t2 ? t3 = $[9] : (t3 = /* @__PURE__ */ jsxs(Fragment, { children: [t1, t2] }), $[8] = t2, $[9] = t3), t3;
2064
+ }
2065
+ function HandbookTool(t0) {
2066
+ let $ = c(10), { tool: t1 } = t0, { options } = t1, { media } = useTheme_v2(), [layoutCollapsed, setLayoutCollapsed] = useState(!1), t2;
2067
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t2 = function handleCollapse() {
2068
+ setLayoutCollapsed(!0);
2069
+ }, $[0] = t2) : t2 = $[0];
2070
+ let handleCollapse = t2, t3;
2071
+ $[1] === Symbol.for("react.memo_cache_sentinel") ? (t3 = function handleExpand() {
2072
+ setLayoutCollapsed(!1);
2073
+ }, $[1] = t3) : t3 = $[1];
2074
+ let handleExpand = t3;
2075
+ if (!isDefined(options)) return null;
2076
+ let t4 = layoutCollapsed ? void 0 : "fill", t5, t6;
2077
+ $[2] === Symbol.for("react.memo_cache_sentinel") ? (t5 = {
2078
+ minHeight: "100%",
2079
+ minWidth: "320px"
2080
+ }, t6 = /* @__PURE__ */ jsx(Panes, {}), $[2] = t5, $[3] = t6) : (t5 = $[2], t6 = $[3]);
2081
+ let t7;
2082
+ $[4] !== media[1] || $[5] !== t4 ? (t7 = /* @__PURE__ */ jsx(PaneLayout, {
2083
+ flex: 1,
2084
+ height: t4,
2085
+ minWidth: media[1],
2086
+ onCollapse: handleCollapse,
2087
+ onExpand: handleExpand,
2088
+ style: t5,
2089
+ children: t6
2090
+ }), $[4] = media[1], $[5] = t4, $[6] = t7) : t7 = $[6];
2091
+ let t8;
2092
+ return $[7] !== options || $[8] !== t7 ? (t8 = /* @__PURE__ */ jsx(HandbookProvider, {
2093
+ ...options,
2094
+ children: t7
2095
+ }), $[7] = options, $[8] = t7, $[9] = t8) : t8 = $[9], t8;
2096
+ }
2097
+ /** Editors the plugin was configured with, so the Structure helper need not be handed them a second time. */
2098
+ let configuredEditors;
2099
+ /**
2100
+ * Records the editors a plugin instance was configured with. A Studio running more than one workspace
2101
+ * keeps only the list from the workspace configured last, so those cases pass the list explicitly.
2102
+ *
2103
+ * @param editors - Email addresses permitted to edit Handbook documents.
2104
+ */
2105
+ function setConfiguredEditors(editors) {
2106
+ configuredEditors = editors;
2107
+ }
2108
+ /**
2109
+ * Checks whether an email address is permitted to edit, treating an absent list as unrestricted access.
2110
+ *
2111
+ * @param editors - Email addresses permitted to edit, defaulting to the configured list.
2112
+ * @param email - The email address to check.
2113
+ * @returns Whether the email is permitted to edit.
2114
+ */
2115
+ function isPermittedEditor(editors, email) {
2116
+ let permitted = editors ?? configuredEditors;
2117
+ return isDefined(permitted) ? isDefined(email) ? permitted.includes(email) : !1 : !0;
2118
+ }
2119
+ function CalloutPreview(t0) {
2120
+ let $ = c(7), { variant, body } = t0, t1 = variant ?? "tip", t2;
2121
+ $[0] === body ? t2 = $[1] : (t2 = body?.map(_temp2), $[0] = body, $[1] = t2);
2122
+ let t3;
2123
+ $[2] === t2 ? t3 = $[3] : (t3 = /* @__PURE__ */ jsx(Stack, {
2124
+ gap: 3,
2125
+ children: t2
2126
+ }), $[2] = t2, $[3] = t3);
2127
+ let t4;
2128
+ return $[4] !== t1 || $[5] !== t3 ? (t4 = /* @__PURE__ */ jsx(CalloutContent, {
2129
+ variant: t1,
2130
+ children: t3
2131
+ }), $[4] = t1, $[5] = t3, $[6] = t4) : t4 = $[6], t4;
2132
+ }
2133
+ function _temp2(t0) {
2134
+ let { _key, children } = t0;
2135
+ return /* @__PURE__ */ jsx("div", {
2136
+ style: { whiteSpace: "pre-wrap" },
2137
+ children: children.map(_temp).join("")
2138
+ }, _key);
2139
+ }
2140
+ function _temp(child) {
2141
+ return child.text;
2142
+ }
2143
+ function CodeDecorator(t0) {
2144
+ let $ = c(2), { children } = t0, t1;
2145
+ return $[0] === children ? t1 = $[1] : (t1 = /* @__PURE__ */ jsx(PortableCode, { children }), $[0] = children, $[1] = t1), t1;
2146
+ }
2147
+ function ParagraphStyle(t0) {
2148
+ let $ = c(2), { children } = t0, t1;
2149
+ return $[0] === children ? t1 = $[1] : (t1 = /* @__PURE__ */ jsx(PortableParagraph, { children }), $[0] = children, $[1] = t1), t1;
2150
+ }
2151
+ function HeadingStyle(t0) {
2152
+ let $ = c(2), { children } = t0, t1;
2153
+ return $[0] === children ? t1 = $[1] : (t1 = /* @__PURE__ */ jsx(PortableHeading, { children }), $[0] = children, $[1] = t1), t1;
2154
+ }
2155
+ function BlockquoteStyle(t0) {
2156
+ let $ = c(2), { children } = t0, t1;
2157
+ return $[0] === children ? t1 = $[1] : (t1 = /* @__PURE__ */ jsx(PortableBlockquote, { children }), $[0] = children, $[1] = t1), t1;
2158
+ }
2159
+ function MessageCircleIcon(props) {
2160
+ let $ = c(3), t0;
2161
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719" }), $[0] = t0) : t0 = $[0];
2162
+ let t1;
2163
+ return $[1] === props ? t1 = $[2] : (t1 = /* @__PURE__ */ jsx("svg", {
2164
+ xmlns: "http://www.w3.org/2000/svg",
2165
+ width: 24,
2166
+ height: 24,
2167
+ viewBox: "0 0 24 24",
2168
+ fill: "none",
2169
+ stroke: "currentColor",
2170
+ strokeWidth: 2,
2171
+ strokeLinecap: "round",
2172
+ strokeLinejoin: "round",
2173
+ ...props,
2174
+ children: t0
2175
+ }), $[1] = props, $[2] = t1), t1;
2176
+ }
2177
+ function LinkIcon(props) {
2178
+ let $ = c(4), t0, t1;
2179
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }), t1 = /* @__PURE__ */ jsx("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" }), $[0] = t0, $[1] = t1) : (t0 = $[0], t1 = $[1]);
2180
+ let t2;
2181
+ return $[2] === props ? t2 = $[3] : (t2 = /* @__PURE__ */ jsxs("svg", {
2182
+ xmlns: "http://www.w3.org/2000/svg",
2183
+ width: 24,
2184
+ height: 24,
2185
+ viewBox: "0 0 24 24",
2186
+ fill: "none",
2187
+ stroke: "currentColor",
2188
+ strokeWidth: 2,
2189
+ strokeLinecap: "round",
2190
+ strokeLinejoin: "round",
2564
2191
  ...props,
2565
- children: t2
2566
- }), $[6] = props, $[7] = t2, $[8] = t3) : t3 = $[8], t3;
2192
+ children: [t0, t1]
2193
+ }), $[2] = props, $[3] = t2), t2;
2567
2194
  }
2568
- function SidebarTab(t0) {
2569
- let $ = c(25), Icon, id, label, props, style;
2570
- $[0] === t0 ? (Icon = $[1], id = $[2], label = $[3], props = $[4], style = $[5]) : ({id, label, icon: Icon, style, ...props} = t0, $[0] = t0, $[1] = Icon, $[2] = id, $[3] = label, $[4] = props, $[5] = style);
2571
- let { activeTab, setActiveTab, setSidebarExpanded } = useHandbookContext(), selected = activeTab === id, t1;
2572
- $[6] !== id || $[7] !== setActiveTab || $[8] !== setSidebarExpanded ? (t1 = () => {
2573
- setActiveTab(id), setSidebarExpanded(!1);
2574
- }, $[6] = id, $[7] = setActiveTab, $[8] = setSidebarExpanded, $[9] = t1) : t1 = $[9];
2195
+ const linkAnnotation = defineArrayMember({
2196
+ name: "link",
2197
+ type: "object",
2198
+ description: "Link applied to the selected text.",
2199
+ icon: createSanityIcon(LinkIcon),
2200
+ preview: {
2201
+ select: { href: "href" },
2202
+ prepare(selection) {
2203
+ let { href } = selection;
2204
+ return { title: href ?? "Link" };
2205
+ }
2206
+ },
2207
+ fields: [defineField({
2208
+ name: "href",
2209
+ type: "url",
2210
+ title: "URL",
2211
+ description: "Web address destination for this link. Supports http, https, mailto, and tel schemes.",
2212
+ validation: (rule) => rule.uri({ scheme: [
2213
+ "http",
2214
+ "https",
2215
+ "mailto",
2216
+ "tel"
2217
+ ] })
2218
+ })]
2219
+ }), calloutType = defineType({
2220
+ name: calloutTypeName,
2221
+ type: "object",
2222
+ title: "Callout",
2223
+ description: "Highlighted message block drawing attention to tips, supplementary information, or warnings.",
2224
+ icon: createSanityIcon(MessageCircleIcon),
2225
+ components: { preview: CalloutPreview },
2226
+ preview: {
2227
+ select: {
2228
+ variant: "variant",
2229
+ body: "body"
2230
+ },
2231
+ prepare(selection) {
2232
+ let { variant, body } = selection;
2233
+ return {
2234
+ title: "Callout",
2235
+ variant,
2236
+ body
2237
+ };
2238
+ }
2239
+ },
2240
+ fields: [defineField({
2241
+ name: "variant",
2242
+ type: "string",
2243
+ description: "Visual style and intent of the callout.",
2244
+ initialValue: "tip",
2245
+ validation: (rule) => rule.required(),
2246
+ options: {
2247
+ list: [
2248
+ {
2249
+ title: "Tip",
2250
+ value: "tip"
2251
+ },
2252
+ {
2253
+ title: "Information",
2254
+ value: "info"
2255
+ },
2256
+ {
2257
+ title: "Warning",
2258
+ value: "warning"
2259
+ }
2260
+ ],
2261
+ layout: "radio",
2262
+ direction: "horizontal"
2263
+ }
2264
+ }), defineField({
2265
+ name: "body",
2266
+ type: "array",
2267
+ description: "Content displayed inside the callout. Supports inline formatting and links.",
2268
+ of: [defineArrayMember({
2269
+ name: "block",
2270
+ type: "block",
2271
+ styles: [{
2272
+ title: "Normal",
2273
+ value: "normal",
2274
+ component: ParagraphStyle
2275
+ }],
2276
+ lists: [],
2277
+ marks: {
2278
+ decorators: [
2279
+ {
2280
+ title: "Bold",
2281
+ value: "strong"
2282
+ },
2283
+ {
2284
+ title: "Italic",
2285
+ value: "em"
2286
+ },
2287
+ {
2288
+ title: "Strikethrough",
2289
+ value: "strike-through"
2290
+ },
2291
+ {
2292
+ title: "Code",
2293
+ value: "code",
2294
+ component: CodeDecorator
2295
+ }
2296
+ ],
2297
+ annotations: [linkAnnotation]
2298
+ }
2299
+ })]
2300
+ })]
2301
+ });
2302
+ function CodePreview(t0) {
2303
+ let $ = c(3), { code, language } = t0;
2304
+ if (!isDefined(code)) return null;
2305
+ let t1;
2306
+ return $[0] !== code || $[1] !== language ? (t1 = /* @__PURE__ */ jsx(CodeContent, {
2307
+ code,
2308
+ language
2309
+ }), $[0] = code, $[1] = language, $[2] = t1) : t1 = $[2], t1;
2310
+ }
2311
+ function CodeIcon(props) {
2312
+ let $ = c(4), t0, t1;
2313
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "m16 18 6-6-6-6" }), t1 = /* @__PURE__ */ jsx("path", { d: "m8 6-6 6 6 6" }), $[0] = t0, $[1] = t1) : (t0 = $[0], t1 = $[1]);
2575
2314
  let t2;
2576
- $[10] === style ? t2 = $[11] : (t2 = {
2577
- cursor: "pointer",
2578
- ...style
2579
- }, $[10] = style, $[11] = t2);
2580
- let t3 = `panel-${id}`, t4;
2581
- $[12] === Symbol.for("react.memo_cache_sentinel") ? (t4 = { opacity: .5 }, $[12] = t4) : t4 = $[12];
2582
- let t5;
2583
- $[13] === Symbol.for("react.memo_cache_sentinel") ? (t5 = /* @__PURE__ */ jsx(Box, {
2584
- style: t4,
2585
- children: /* @__PURE__ */ jsx(Text, {
2586
- muted: !0,
2587
- size: 1,
2588
- children: /* @__PURE__ */ jsx(ChevronRightIcon, {})
2589
- })
2590
- }), $[13] = t5) : t5 = $[13];
2591
- let t6;
2592
- $[14] !== Icon || $[15] !== label ? (t6 = /* @__PURE__ */ jsx(SanityDefaultPreview, {
2593
- status: t5,
2594
- icon: Icon,
2595
- layout: "compact",
2596
- title: label
2597
- }), $[14] = Icon, $[15] = label, $[16] = t6) : t6 = $[16];
2598
- let t7;
2599
- return $[17] !== id || $[18] !== props || $[19] !== selected || $[20] !== t1 || $[21] !== t2 || $[22] !== t3 || $[23] !== t6 ? (t7 = /* @__PURE__ */ jsx(PreviewCard, {
2600
- id,
2601
- as: "button",
2602
- "data-as": "button",
2603
- selected,
2604
- marginBottom: 1,
2605
- radius: 2,
2606
- sizing: "border",
2607
- tabIndex: -1,
2608
- tone: "inherit",
2609
- onClick: t1,
2610
- style: t2,
2611
- "aria-controls": t3,
2612
- __unstable_focusRing: !0,
2315
+ return $[2] === props ? t2 = $[3] : (t2 = /* @__PURE__ */ jsxs("svg", {
2316
+ xmlns: "http://www.w3.org/2000/svg",
2317
+ width: 24,
2318
+ height: 24,
2319
+ viewBox: "0 0 24 24",
2320
+ fill: "none",
2321
+ stroke: "currentColor",
2322
+ strokeWidth: 2,
2323
+ strokeLinecap: "round",
2324
+ strokeLinejoin: "round",
2613
2325
  ...props,
2614
- children: t6
2615
- }), $[17] = id, $[18] = props, $[19] = selected, $[20] = t1, $[21] = t2, $[22] = t3, $[23] = t6, $[24] = t7) : t7 = $[24], t7;
2326
+ children: [t0, t1]
2327
+ }), $[2] = props, $[3] = t2), t2;
2328
+ }
2329
+ const codeType = defineType({
2330
+ name: codeTypeName,
2331
+ type: "object",
2332
+ title: "Code",
2333
+ description: "Syntax-highlighted code block with language selection.",
2334
+ icon: createSanityIcon(CodeIcon),
2335
+ components: { preview: CodePreview },
2336
+ preview: { select: {
2337
+ code: "code",
2338
+ language: "language"
2339
+ } },
2340
+ fields: [defineField({
2341
+ name: "code",
2342
+ type: "text",
2343
+ description: "The source code to display."
2344
+ }), defineField({
2345
+ name: "language",
2346
+ type: "string",
2347
+ description: "Programming language used for syntax highlighting.",
2348
+ options: { list: [
2349
+ {
2350
+ title: "CSS",
2351
+ value: "css"
2352
+ },
2353
+ {
2354
+ title: "GROQ",
2355
+ value: "groq"
2356
+ },
2357
+ {
2358
+ title: "HTML",
2359
+ value: "html"
2360
+ },
2361
+ {
2362
+ title: "JavaScript",
2363
+ value: "javascript"
2364
+ },
2365
+ {
2366
+ title: "JSON",
2367
+ value: "json"
2368
+ },
2369
+ {
2370
+ title: "Plain Text",
2371
+ value: "text"
2372
+ },
2373
+ {
2374
+ title: "React",
2375
+ value: "tsx"
2376
+ },
2377
+ {
2378
+ title: "Shell",
2379
+ value: "shell"
2380
+ },
2381
+ {
2382
+ title: "TypeScript",
2383
+ value: "typescript"
2384
+ }
2385
+ ] }
2386
+ })]
2387
+ });
2388
+ function HorizontalRulePreview(_props) {
2389
+ let $ = c(1), t0;
2390
+ return $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx(HorizontalRuleContent, { style: { marginBlock: 8 } }), $[0] = t0) : t0 = $[0], t0;
2616
2391
  }
2617
- function Sidebar(props) {
2618
- let $ = c(14), { sidebarTitle } = useHandbookContext(), sections = useSections(), t0;
2619
- $[0] === sections ? t0 = $[1] : (t0 = sections.flatMap(_temp2), $[0] = sections, $[1] = t0);
2620
- let items = t0, t1;
2621
- $[2] === items ? t1 = $[3] : (t1 = function getItemDisabled(virtualIndex) {
2622
- return items[virtualIndex]?.type === "heading";
2623
- }, $[2] = items, $[3] = t1);
2624
- let getItemDisabled = t1, t2;
2625
- $[4] === sidebarTitle ? t2 = $[5] : (t2 = /* @__PURE__ */ jsx(PaneHeader, { title: sidebarTitle }), $[4] = sidebarTitle, $[5] = t2);
2392
+ function SeparatorHorizontalIcon(props) {
2393
+ let $ = c(5), t0, t1, t2;
2394
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "m16 16-4 4-4-4" }), t1 = /* @__PURE__ */ jsx("path", { d: "M3 12h18" }), t2 = /* @__PURE__ */ jsx("path", { d: "m8 8 4-4 4 4" }), $[0] = t0, $[1] = t1, $[2] = t2) : (t0 = $[0], t1 = $[1], t2 = $[2]);
2626
2395
  let t3;
2627
- $[6] !== getItemDisabled || $[7] !== items || $[8] !== sidebarTitle ? (t3 = /* @__PURE__ */ jsx(PaneContent, {
2628
- overflow: "auto",
2629
- children: /* @__PURE__ */ jsx(CommandList, {
2630
- activeItemDataAttr: "data-hovered",
2631
- ariaLabel: sidebarTitle,
2632
- canReceiveFocus: !0,
2633
- getItemDisabled,
2634
- itemHeight: 37,
2635
- items,
2636
- onlyShowSelectionWhenActive: !0,
2637
- paddingBottom: 1,
2638
- paddingX: 3,
2639
- renderItem: _temp3,
2640
- wrapAround: !1
2641
- })
2642
- }), $[6] = getItemDisabled, $[7] = items, $[8] = sidebarTitle, $[9] = t3) : t3 = $[9];
2643
- let t4;
2644
- return $[10] !== props || $[11] !== t2 || $[12] !== t3 ? (t4 = /* @__PURE__ */ jsxs(Pane, {
2645
- id: "handbook-sidebar",
2646
- currentMaxWidth: 350,
2647
- minWidth: 320,
2648
- maxWidth: 640,
2396
+ return $[3] === props ? t3 = $[4] : (t3 = /* @__PURE__ */ jsxs("svg", {
2397
+ xmlns: "http://www.w3.org/2000/svg",
2398
+ width: 24,
2399
+ height: 24,
2400
+ viewBox: "0 0 24 24",
2401
+ fill: "none",
2402
+ stroke: "currentColor",
2403
+ strokeWidth: 2,
2404
+ strokeLinecap: "round",
2405
+ strokeLinejoin: "round",
2649
2406
  ...props,
2650
- children: [t2, t3]
2651
- }), $[10] = props, $[11] = t2, $[12] = t3, $[13] = t4) : t4 = $[13], t4;
2652
- }
2653
- function _temp3(item) {
2654
- return item.type === "heading" ? /* @__PURE__ */ jsx(SidebarHeading, { title: item.title }) : /* @__PURE__ */ jsx(SidebarTab, {
2655
- id: item.id,
2656
- label: item.label,
2657
- icon: item.icon
2658
- });
2407
+ children: [
2408
+ t0,
2409
+ t1,
2410
+ t2
2411
+ ]
2412
+ }), $[3] = props, $[4] = t3), t3;
2659
2413
  }
2660
- function _temp2(t0) {
2661
- let { title, entries } = t0;
2662
- return [{
2663
- type: "heading",
2664
- title
2665
- }, ...entries.map(_temp)];
2414
+ const horizontalRuleType = defineType({
2415
+ name: horizontalRuleTypeName,
2416
+ type: "object",
2417
+ title: "Horizontal Rule",
2418
+ description: "Visual divider between sections of content.",
2419
+ icon: createSanityIcon(SeparatorHorizontalIcon),
2420
+ components: { preview: HorizontalRulePreview },
2421
+ preview: { prepare() {
2422
+ return { title: "Horizontal Rule" };
2423
+ } },
2424
+ fields: [defineField({
2425
+ name: "style",
2426
+ type: "string",
2427
+ description: "Reserved. A horizontal rule carries no authored content.",
2428
+ hidden: !0
2429
+ })]
2430
+ });
2431
+ function ImagePreview(t0) {
2432
+ let $ = c(5), { url, alt, caption } = t0;
2433
+ if (!isDefined(url)) return null;
2434
+ let t1;
2435
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t1 = { padding: 8 }, $[0] = t1) : t1 = $[0];
2436
+ let t2;
2437
+ return $[1] !== alt || $[2] !== caption || $[3] !== url ? (t2 = /* @__PURE__ */ jsx(ImageContent, {
2438
+ url,
2439
+ alt,
2440
+ caption,
2441
+ style: t1
2442
+ }), $[1] = alt, $[2] = caption, $[3] = url, $[4] = t2) : t2 = $[4], t2;
2666
2443
  }
2667
- function _temp(entry) {
2668
- return {
2669
- type: "tab",
2670
- id: entry.id,
2671
- label: entry.title,
2672
- icon: entry.icon
2673
- };
2444
+ function ImageIcon(props) {
2445
+ let $ = c(5), t0, t1, t2;
2446
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("rect", {
2447
+ width: "18",
2448
+ height: "18",
2449
+ x: "3",
2450
+ y: "3",
2451
+ rx: "2",
2452
+ ry: "2"
2453
+ }), t1 = /* @__PURE__ */ jsx("circle", {
2454
+ cx: "9",
2455
+ cy: "9",
2456
+ r: "2"
2457
+ }), t2 = /* @__PURE__ */ jsx("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" }), $[0] = t0, $[1] = t1, $[2] = t2) : (t0 = $[0], t1 = $[1], t2 = $[2]);
2458
+ let t3;
2459
+ return $[3] === props ? t3 = $[4] : (t3 = /* @__PURE__ */ jsxs("svg", {
2460
+ xmlns: "http://www.w3.org/2000/svg",
2461
+ width: 24,
2462
+ height: 24,
2463
+ viewBox: "0 0 24 24",
2464
+ fill: "none",
2465
+ stroke: "currentColor",
2466
+ strokeWidth: 2,
2467
+ strokeLinecap: "round",
2468
+ strokeLinejoin: "round",
2469
+ ...props,
2470
+ children: [
2471
+ t0,
2472
+ t1,
2473
+ t2
2474
+ ]
2475
+ }), $[3] = props, $[4] = t3), t3;
2674
2476
  }
2675
- function Panes() {
2676
- let $ = c(10), { activeTab, sidebarExpanded } = useHandbookContext(), paneLayout = useContext(PaneLayoutContext), t0;
2677
- $[0] === activeTab ? t0 = $[1] : (t0 = isDefined(activeTab), $[0] = activeTab, $[1] = t0);
2678
- let hasContent = t0;
2679
- if (paneLayout?.collapsed === !0) {
2680
- let t1;
2681
- return $[2] !== hasContent || $[3] !== sidebarExpanded ? (t1 = jsx(sidebarExpanded || !hasContent ? Sidebar : Content, {}), $[2] = hasContent, $[3] = sidebarExpanded, $[4] = t1) : t1 = $[4], t1;
2682
- }
2477
+ const imageType = defineType({
2478
+ name: imageTypeName,
2479
+ type: "object",
2480
+ title: "Image",
2481
+ description: "Image with an optional caption and alternative text.",
2482
+ icon: createSanityIcon(ImageIcon),
2483
+ components: { preview: ImagePreview },
2484
+ preview: { select: {
2485
+ caption: "caption",
2486
+ alt: "alt",
2487
+ url: "asset.asset.url"
2488
+ } },
2489
+ fields: [
2490
+ defineField({
2491
+ name: "asset",
2492
+ type: "image",
2493
+ title: "Image",
2494
+ description: "Upload or select an image from the media library.",
2495
+ options: { hotspot: !0 }
2496
+ }),
2497
+ defineField({
2498
+ name: "caption",
2499
+ type: "string",
2500
+ description: "Caption text displayed below the image, such as a credit or a note."
2501
+ }),
2502
+ defineField({
2503
+ name: "alt",
2504
+ type: "string",
2505
+ title: "Alternative Text",
2506
+ description: "Describes what the image shows for people who cannot see it. Don't repeat the caption here."
2507
+ })
2508
+ ]
2509
+ });
2510
+ function VideoPreview(t0) {
2511
+ let $ = c(4), { url, caption } = t0;
2512
+ if (!isDefined(url)) return null;
2683
2513
  let t1;
2684
- $[5] === Symbol.for("react.memo_cache_sentinel") ? (t1 = /* @__PURE__ */ jsx(Sidebar, {}), $[5] = t1) : t1 = $[5];
2514
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t1 = { padding: 8 }, $[0] = t1) : t1 = $[0];
2685
2515
  let t2;
2686
- $[6] === hasContent ? t2 = $[7] : (t2 = hasContent && /* @__PURE__ */ jsx(Content, {}), $[6] = hasContent, $[7] = t2);
2687
- let t3;
2688
- return $[8] === t2 ? t3 = $[9] : (t3 = /* @__PURE__ */ jsxs(Fragment, { children: [t1, t2] }), $[8] = t2, $[9] = t3), t3;
2516
+ return $[1] !== caption || $[2] !== url ? (t2 = /* @__PURE__ */ jsx(VideoContent, {
2517
+ url,
2518
+ caption,
2519
+ style: t1
2520
+ }), $[1] = caption, $[2] = url, $[3] = t2) : t2 = $[3], t2;
2689
2521
  }
2690
- function HandbookTool(t0) {
2691
- let $ = c(10), { tool: t1 } = t0, { options } = t1, { media } = useTheme_v2(), [layoutCollapsed, setLayoutCollapsed] = useState(!1), t2;
2692
- $[0] === Symbol.for("react.memo_cache_sentinel") ? (t2 = function handleCollapse() {
2693
- setLayoutCollapsed(!0);
2694
- }, $[0] = t2) : t2 = $[0];
2695
- let handleCollapse = t2, t3;
2696
- $[1] === Symbol.for("react.memo_cache_sentinel") ? (t3 = function handleExpand() {
2697
- setLayoutCollapsed(!1);
2698
- }, $[1] = t3) : t3 = $[1];
2699
- let handleExpand = t3;
2700
- if (!isDefined(options)) return null;
2701
- let t4 = layoutCollapsed ? void 0 : "fill", t5, t6;
2702
- $[2] === Symbol.for("react.memo_cache_sentinel") ? (t5 = {
2703
- minHeight: "100%",
2704
- minWidth: "320px"
2705
- }, t6 = /* @__PURE__ */ jsx(Panes, {}), $[2] = t5, $[3] = t6) : (t5 = $[2], t6 = $[3]);
2706
- let t7;
2707
- $[4] !== media[1] || $[5] !== t4 ? (t7 = /* @__PURE__ */ jsx(PaneLayout, {
2708
- flex: 1,
2709
- height: t4,
2710
- minWidth: media[1],
2711
- onCollapse: handleCollapse,
2712
- onExpand: handleExpand,
2713
- style: t5,
2714
- children: t6
2715
- }), $[4] = media[1], $[5] = t4, $[6] = t7) : t7 = $[6];
2522
+ function FilmIcon(props) {
2523
+ let $ = c(10), t0, t1, t2, t3, t4, t5, t6, t7;
2524
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("rect", {
2525
+ x: "3",
2526
+ y: "3",
2527
+ width: "18",
2528
+ height: "18",
2529
+ rx: "2"
2530
+ }), t1 = /* @__PURE__ */ jsx("path", { d: "M7 3v18" }), t2 = /* @__PURE__ */ jsx("path", { d: "M3 7.5h4" }), t3 = /* @__PURE__ */ jsx("path", { d: "M3 12h18" }), t4 = /* @__PURE__ */ jsx("path", { d: "M3 16.5h4" }), t5 = /* @__PURE__ */ jsx("path", { d: "M17 3v18" }), t6 = /* @__PURE__ */ jsx("path", { d: "M17 7.5h4" }), t7 = /* @__PURE__ */ jsx("path", { d: "M17 16.5h4" }), $[0] = t0, $[1] = t1, $[2] = t2, $[3] = t3, $[4] = t4, $[5] = t5, $[6] = t6, $[7] = t7) : (t0 = $[0], t1 = $[1], t2 = $[2], t3 = $[3], t4 = $[4], t5 = $[5], t6 = $[6], t7 = $[7]);
2716
2531
  let t8;
2717
- return $[7] !== options || $[8] !== t7 ? (t8 = /* @__PURE__ */ jsx(HandbookProvider, {
2718
- ...options,
2719
- children: t7
2720
- }), $[7] = options, $[8] = t7, $[9] = t8) : t8 = $[9], t8;
2532
+ return $[8] === props ? t8 = $[9] : (t8 = /* @__PURE__ */ jsxs("svg", {
2533
+ xmlns: "http://www.w3.org/2000/svg",
2534
+ width: 24,
2535
+ height: 24,
2536
+ viewBox: "0 0 24 24",
2537
+ fill: "none",
2538
+ stroke: "currentColor",
2539
+ strokeWidth: 2,
2540
+ strokeLinecap: "round",
2541
+ strokeLinejoin: "round",
2542
+ ...props,
2543
+ children: [
2544
+ t0,
2545
+ t1,
2546
+ t2,
2547
+ t3,
2548
+ t4,
2549
+ t5,
2550
+ t6,
2551
+ t7
2552
+ ]
2553
+ }), $[8] = props, $[9] = t8), t8;
2554
+ }
2555
+ const videoType = defineType({
2556
+ name: videoTypeName,
2557
+ type: "object",
2558
+ title: "Video",
2559
+ description: "Video with an optional caption.",
2560
+ icon: createSanityIcon(FilmIcon),
2561
+ components: { preview: VideoPreview },
2562
+ preview: { select: {
2563
+ caption: "caption",
2564
+ url: "asset.asset.url"
2565
+ } },
2566
+ fields: [defineField({
2567
+ name: "asset",
2568
+ type: "file",
2569
+ title: "Video",
2570
+ description: "Upload or select a video from the media library.",
2571
+ options: { accept: "video/*" }
2572
+ }), defineField({
2573
+ name: "caption",
2574
+ type: "string",
2575
+ description: "Caption text displayed below the video, such as a credit or a note."
2576
+ })]
2577
+ });
2578
+ function ListItemStyle(t0) {
2579
+ let $ = c(3), { children } = t0, t1;
2580
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t1 = { marginTop: "0.375em" }, $[0] = t1) : t1 = $[0];
2581
+ let t2;
2582
+ return $[1] === children ? t2 = $[2] : (t2 = /* @__PURE__ */ jsx(Text, {
2583
+ size: 1,
2584
+ style: t1,
2585
+ children
2586
+ }), $[1] = children, $[2] = t2), t2;
2721
2587
  }
2722
- /** Editors the plugin was configured with, so the Structure helper need not be handed them a second time. */
2723
- let configuredEditors;
2724
2588
  /**
2725
- * Records the editors a plugin instance was configured with. A Studio running more than one workspace
2726
- * keeps only the list from the workspace configured last, so those cases pass the list explicitly.
2589
+ * Creates the Portable Text content field for Handbook guides, offering the built-in blocks alongside
2590
+ * any a consumer registered.
2727
2591
  *
2728
- * @param editors - Email addresses permitted to edit Handbook documents.
2592
+ * @param customBlocks - Custom block definitions registered by the consumer.
2593
+ * @returns A field definition for the guide content array.
2729
2594
  */
2730
- function setConfiguredEditors(editors) {
2731
- configuredEditors = editors;
2595
+ function createGuideContentField(customBlocks = []) {
2596
+ return defineField({
2597
+ name: "content",
2598
+ type: "array",
2599
+ description: "Rich text with formatting, headings, lists, images, code blocks, and custom blocks.",
2600
+ of: [
2601
+ defineArrayMember({
2602
+ name: "block",
2603
+ type: "block",
2604
+ styles: [
2605
+ {
2606
+ title: "Paragraph",
2607
+ value: "normal",
2608
+ component: ParagraphStyle
2609
+ },
2610
+ {
2611
+ title: "Heading",
2612
+ value: "h2",
2613
+ component: HeadingStyle
2614
+ },
2615
+ {
2616
+ title: "Blockquote",
2617
+ value: "blockquote",
2618
+ component: BlockquoteStyle
2619
+ }
2620
+ ],
2621
+ lists: [{
2622
+ title: "Bullet",
2623
+ value: "bullet",
2624
+ component: ListItemStyle
2625
+ }, {
2626
+ title: "Number",
2627
+ value: "number",
2628
+ component: ListItemStyle
2629
+ }],
2630
+ marks: {
2631
+ decorators: [
2632
+ {
2633
+ title: "Bold",
2634
+ value: "strong"
2635
+ },
2636
+ {
2637
+ title: "Italic",
2638
+ value: "em"
2639
+ },
2640
+ {
2641
+ title: "Strikethrough",
2642
+ value: "strike-through"
2643
+ },
2644
+ {
2645
+ title: "Code",
2646
+ value: "code",
2647
+ component: CodeDecorator
2648
+ }
2649
+ ],
2650
+ annotations: [linkAnnotation]
2651
+ }
2652
+ }),
2653
+ defineArrayMember({
2654
+ name: imageTypeName,
2655
+ type: imageTypeName
2656
+ }),
2657
+ defineArrayMember({
2658
+ name: videoTypeName,
2659
+ type: videoTypeName
2660
+ }),
2661
+ defineArrayMember({
2662
+ name: codeTypeName,
2663
+ type: codeTypeName
2664
+ }),
2665
+ defineArrayMember({
2666
+ name: calloutTypeName,
2667
+ type: calloutTypeName
2668
+ }),
2669
+ defineArrayMember({
2670
+ name: horizontalRuleTypeName,
2671
+ type: horizontalRuleTypeName
2672
+ }),
2673
+ ...customBlocks.map((block) => defineArrayMember({
2674
+ name: block.schema.name,
2675
+ type: block.schema.name
2676
+ }))
2677
+ ]
2678
+ });
2732
2679
  }
2733
2680
  /**
2734
- * Checks whether an email address is permitted to edit, treating an absent list as unrestricted access.
2681
+ * Creates the document type a single guide is authored as, with its content field offering the
2682
+ * built-in blocks alongside any a consumer registered.
2735
2683
  *
2736
- * @param editors - Email addresses permitted to edit, defaulting to the configured list.
2737
- * @param email - The email address to check.
2738
- * @returns Whether the email is permitted to edit.
2684
+ * @param customBlocks - Custom block definitions registered by the consumer.
2685
+ * @returns A document type definition for Handbook guides.
2739
2686
  */
2740
- function isPermittedEditor(editors, email) {
2741
- let permitted = editors ?? configuredEditors;
2742
- return isDefined(permitted) ? isDefined(email) ? permitted.includes(email) : !1 : !0;
2687
+ function createGuideType(customBlocks = []) {
2688
+ return defineType({
2689
+ name: guideTypeName,
2690
+ type: "document",
2691
+ title: "Handbook Guide",
2692
+ description: "Handbook page authored with rich text, images, and custom blocks.",
2693
+ icon: createSanityIcon(BookOpenTextIcon),
2694
+ preview: {
2695
+ select: {
2696
+ title: "title",
2697
+ description: "description"
2698
+ },
2699
+ prepare(selection) {
2700
+ let { title, description } = selection;
2701
+ return {
2702
+ title: title ?? "Untitled",
2703
+ subtitle: description
2704
+ };
2705
+ }
2706
+ },
2707
+ fields: [
2708
+ defineField({
2709
+ name: "title",
2710
+ type: "string",
2711
+ description: "Appears in the Handbook sidebar and as the guide heading.",
2712
+ validation: (rule) => rule.required()
2713
+ }),
2714
+ defineField({
2715
+ name: "description",
2716
+ type: "string",
2717
+ description: "Short introduction text displayed below the guide heading."
2718
+ }),
2719
+ createGuideContentField(customBlocks)
2720
+ ]
2721
+ });
2743
2722
  }
2744
- /**
2745
- * Creates a Handbook tool for Sanity Studio, generating documentation from document type schemas
2746
- * alongside the Portable Text guides authored in the dataset.
2747
- *
2748
- * @param config - Plugin configuration.
2749
- * @returns Sanity plugin definition.
2750
- * @public
2751
- */
2752
- const handbookPlugin = definePlugin((config) => {
2723
+ function ListPlusIcon(props) {
2724
+ let $ = c(7), t0, t1, t2, t3, t4;
2725
+ $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("path", { d: "M16 5H3" }), t1 = /* @__PURE__ */ jsx("path", { d: "M11 12H3" }), t2 = /* @__PURE__ */ jsx("path", { d: "M16 19H3" }), t3 = /* @__PURE__ */ jsx("path", { d: "M18 9v6" }), t4 = /* @__PURE__ */ jsx("path", { d: "M21 12h-6" }), $[0] = t0, $[1] = t1, $[2] = t2, $[3] = t3, $[4] = t4) : (t0 = $[0], t1 = $[1], t2 = $[2], t3 = $[3], t4 = $[4]);
2726
+ let t5;
2727
+ return $[5] === props ? t5 = $[6] : (t5 = /* @__PURE__ */ jsxs("svg", {
2728
+ xmlns: "http://www.w3.org/2000/svg",
2729
+ width: 24,
2730
+ height: 24,
2731
+ viewBox: "0 0 24 24",
2732
+ fill: "none",
2733
+ stroke: "currentColor",
2734
+ strokeWidth: 2,
2735
+ strokeLinecap: "round",
2736
+ strokeLinejoin: "round",
2737
+ ...props,
2738
+ children: [
2739
+ t0,
2740
+ t1,
2741
+ t2,
2742
+ t3,
2743
+ t4
2744
+ ]
2745
+ }), $[5] = props, $[6] = t5), t5;
2746
+ }
2747
+ const handbookType = defineType({
2748
+ name: handbookTypeName,
2749
+ type: "document",
2750
+ title: "Handbook",
2751
+ description: "Defines the groups of guides shown in the Handbook sidebar, and the order they appear in.",
2752
+ icon: createSanityIcon(BookTextIcon),
2753
+ preview: { prepare() {
2754
+ return { title: "Handbook" };
2755
+ } },
2756
+ fields: [defineField({
2757
+ name: "groups",
2758
+ type: "array",
2759
+ description: "Ordered list of groups displayed in the Handbook sidebar. Each group contains a title and an ordered list of guide references.",
2760
+ of: [defineArrayMember({
2761
+ name: "group",
2762
+ type: "object",
2763
+ description: "Named section of the Handbook sidebar holding an ordered list of guides.",
2764
+ icon: createSanityIcon(ListPlusIcon),
2765
+ fields: [defineField({
2766
+ name: "title",
2767
+ type: "string",
2768
+ description: "Heading displayed above this group of guides in the sidebar.",
2769
+ validation: (rule) => rule.required()
2770
+ }), defineField({
2771
+ name: "guides",
2772
+ type: "array",
2773
+ description: "Ordered list of guides within this group. Drag to reorder.",
2774
+ of: [defineArrayMember({
2775
+ name: "guide",
2776
+ type: "reference",
2777
+ to: [{ type: guideTypeName }]
2778
+ })]
2779
+ })],
2780
+ preview: {
2781
+ select: {
2782
+ title: "title",
2783
+ guide0: "guides.0.title",
2784
+ guide1: "guides.1.title",
2785
+ guide2: "guides.2.title"
2786
+ },
2787
+ prepare(selection) {
2788
+ let { title, guide0, guide1, guide2 } = selection, shown = [
2789
+ guide0,
2790
+ guide1,
2791
+ guide2
2792
+ ].filter((guide) => isDefined(guide)).slice(0, 2), hasMore = isDefined(guide2);
2793
+ function formatSubtitle() {
2794
+ return isDefined(shown) ? hasMore ? `${shown.join(", ")}, and others` : shown.join(" and ") : "No guides selected";
2795
+ }
2796
+ return {
2797
+ title: title ?? "Group",
2798
+ subtitle: formatSubtitle()
2799
+ };
2800
+ }
2801
+ }
2802
+ })]
2803
+ })]
2804
+ }), handbookPlugin = definePlugin((config) => {
2753
2805
  let { title, sidebarTitle, roles, blocks, editors, undocumentedFieldMessage } = config;
2754
2806
  setConfiguredEditors(editors);
2755
2807
  let resolved = {
@@ -2759,7 +2811,7 @@ const handbookPlugin = definePlugin((config) => {
2759
2811
  undocumentedFieldMessage: undocumentedFieldMessage ?? "This field has not been documented yet. Contact your development team for guidance."
2760
2812
  }, guideType = createGuideType(resolved.blocks);
2761
2813
  return {
2762
- name: "@driftime/sanity-plugin-handbook",
2814
+ name: pluginName,
2763
2815
  schema: { types: [
2764
2816
  handbookType,
2765
2817
  guideType,