camox 0.13.0 → 0.14.1

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.
@@ -271,8 +271,10 @@ declare function createApp({
271
271
  name: string;
272
272
  children: (item: any, index: number) => React.ReactNode;
273
273
  }) => React.ReactNode;
274
+ useSetting: (name: string) => unknown;
274
275
  }, index: number) => React.ReactNode;
275
276
  }) => React.ReactNode;
277
+ useSetting: <F extends string>(name: F) => never;
276
278
  }, index: number) => React.ReactNode;
277
279
  }) => _$react_jsx_runtime0.JSX.Element;
278
280
  useSetting: <K extends string>(name: K) => unknown;
@@ -593,8 +595,10 @@ declare function createApp({
593
595
  name: string;
594
596
  children: (item: any, index: number) => React.ReactNode;
595
597
  }) => React.ReactNode;
598
+ useSetting: (name: string) => unknown;
596
599
  }, index: number) => React.ReactNode;
597
600
  }) => React.ReactNode;
601
+ useSetting: <F extends string>(name: F) => never;
598
602
  }, index: number) => React.ReactNode;
599
603
  }) => _$react_jsx_runtime0.JSX.Element;
600
604
  useSetting: <K extends string>(name: K) => unknown;
@@ -1,4 +1,4 @@
1
- import { EmbedURL, FileValue, ImageValue, LinkValue, ToMarkdownBuilder, Type } from "./lib/contentType.js";
1
+ import { EmbedURL, FileValue, ImageValue, ItemSettingsBrand, LinkValue, ToMarkdownBuilder, Type } from "./lib/contentType.js";
2
2
  import * as _$_sinclair_typebox0 from "@sinclair/typebox";
3
3
  import { Static, TSchema, Type as Type$1 } from "@sinclair/typebox";
4
4
  import * as React from "react";
@@ -61,13 +61,16 @@ interface CreateBlockOptions<TSchemaShape extends Record<string, TSchema> = Reco
61
61
  /**
62
62
  * Builder for rendering block content as markdown.
63
63
  * `c` is a proxy typed on `content` keys — `c.title`, `c.description`, etc.
64
- * Each returned entry becomes a paragraph (joined with `\n\n`).
65
- * Lines where all referenced fields resolve to empty are omitted at render time.
64
+ * `s` is a proxy typed on `settings` keys — call a boolean setting with a line
65
+ * (`s.showCta(c.cta)`) or an enum with a value (`s.variant("banner", [...])`)
66
+ * to wrap lines in a conditional. Each returned entry becomes a paragraph
67
+ * (joined with `\n\n`). Lines where all referenced fields resolve to empty
68
+ * (or whose condition is false) are omitted at render time.
66
69
  *
67
70
  * @example
68
- * toMarkdown: (c) => [`# ${c.title}`, c.description, c.illustration, c.cta]
71
+ * toMarkdown: (c, s) => [`# ${c.title}`, c.description, s.showCta(c.cta)]
69
72
  */
70
- toMarkdown: ToMarkdownBuilder<TSchemaShape>;
73
+ toMarkdown: ToMarkdownBuilder<TSchemaShape, TSettingsShape>;
71
74
  }
72
75
  interface BlockData<TContent> {
73
76
  _id: number;
@@ -90,6 +93,7 @@ interface PeekItem {
90
93
  parentItemId: number | null;
91
94
  fieldName: string;
92
95
  content: unknown;
96
+ settings: Record<string, unknown> | null;
93
97
  summary: string;
94
98
  position: string;
95
99
  createdAt: number;
@@ -100,6 +104,7 @@ interface RepeatableItemSeed {
100
104
  parentTempId: string | null;
101
105
  fieldName: string;
102
106
  content: Record<string, unknown>;
107
+ settings?: Record<string, unknown>;
103
108
  position: string;
104
109
  }
105
110
  declare function createBlock<TSchemaShape extends Record<string, TSchema>, TSettingsShape extends Record<string, TSchema> = Record<string, never>, TLayoutOnly extends boolean = false>(options: CreateBlockOptions<TSchemaShape, TSettingsShape, TLayoutOnly>): {
@@ -1055,8 +1060,30 @@ declare function createBlock<TSchemaShape extends Record<string, TSchema>, TSett
1055
1060
  name: string;
1056
1061
  children: (item: any, index: number) => React.ReactNode;
1057
1062
  }) => React.ReactNode;
1063
+ useSetting: (name: string) => unknown;
1058
1064
  }, index: number) => React.ReactNode;
1059
1065
  }) => React.ReactNode;
1066
+ useSetting: <F extends keyof (TSchemaShape[K] extends {
1067
+ readonly [ItemSettingsBrand]?: infer S;
1068
+ } ? S extends Record<string, TSchema> ? _$_sinclair_typebox0.Evaluate<Readonly<Partial<Pick<{ [K_6 in keyof S]: (S[K_6] & {
1069
+ params: unknown[] & [];
1070
+ })["static"] }, { [K_7 in keyof S]: S[K_7] extends _$_sinclair_typebox0.TReadonly<TSchema> ? S[K_7] extends _$_sinclair_typebox0.TOptional<S[K_7]> ? K_7 : never : never }[keyof S]>>> & Readonly<Pick<{ [K_6 in keyof S]: (S[K_6] & {
1071
+ params: unknown[] & [];
1072
+ })["static"] }, { [K_8 in keyof S]: S[K_8] extends _$_sinclair_typebox0.TReadonly<TSchema> ? S[K_8] extends _$_sinclair_typebox0.TOptional<S[K_8]> ? never : K_8 : never }[keyof S]>> & Partial<Pick<{ [K_6 in keyof S]: (S[K_6] & {
1073
+ params: unknown[] & [];
1074
+ })["static"] }, { [K_9 in keyof S]: S[K_9] extends _$_sinclair_typebox0.TOptional<TSchema> ? S[K_9] extends _$_sinclair_typebox0.TReadonly<S[K_9]> ? never : K_9 : never }[keyof S]>> & Required<Pick<{ [K_6 in keyof S]: (S[K_6] & {
1075
+ params: unknown[] & [];
1076
+ })["static"] }, Exclude<keyof S, { [K_7 in keyof S]: S[K_7] extends _$_sinclair_typebox0.TReadonly<TSchema> ? S[K_7] extends _$_sinclair_typebox0.TOptional<S[K_7]> ? K_7 : never : never }[keyof S] | { [K_8 in keyof S]: S[K_8] extends _$_sinclair_typebox0.TReadonly<TSchema> ? S[K_8] extends _$_sinclair_typebox0.TOptional<S[K_8]> ? never : K_8 : never }[keyof S] | { [K_9 in keyof S]: S[K_9] extends _$_sinclair_typebox0.TOptional<TSchema> ? S[K_9] extends _$_sinclair_typebox0.TReadonly<S[K_9]> ? never : K_9 : never }[keyof S]>>>> : Record<string, never> : Record<string, never>)>(name: F) => (TSchemaShape[K] extends {
1077
+ readonly [ItemSettingsBrand]?: infer S;
1078
+ } ? S extends Record<string, TSchema> ? _$_sinclair_typebox0.Evaluate<Readonly<Partial<Pick<{ [K_6 in keyof S]: (S[K_6] & {
1079
+ params: unknown[] & [];
1080
+ })["static"] }, { [K_7 in keyof S]: S[K_7] extends _$_sinclair_typebox0.TReadonly<TSchema> ? S[K_7] extends _$_sinclair_typebox0.TOptional<S[K_7]> ? K_7 : never : never }[keyof S]>>> & Readonly<Pick<{ [K_6 in keyof S]: (S[K_6] & {
1081
+ params: unknown[] & [];
1082
+ })["static"] }, { [K_8 in keyof S]: S[K_8] extends _$_sinclair_typebox0.TReadonly<TSchema> ? S[K_8] extends _$_sinclair_typebox0.TOptional<S[K_8]> ? never : K_8 : never }[keyof S]>> & Partial<Pick<{ [K_6 in keyof S]: (S[K_6] & {
1083
+ params: unknown[] & [];
1084
+ })["static"] }, { [K_9 in keyof S]: S[K_9] extends _$_sinclair_typebox0.TOptional<TSchema> ? S[K_9] extends _$_sinclair_typebox0.TReadonly<S[K_9]> ? never : K_9 : never }[keyof S]>> & Required<Pick<{ [K_6 in keyof S]: (S[K_6] & {
1085
+ params: unknown[] & [];
1086
+ })["static"] }, Exclude<keyof S, { [K_7 in keyof S]: S[K_7] extends _$_sinclair_typebox0.TReadonly<TSchema> ? S[K_7] extends _$_sinclair_typebox0.TOptional<S[K_7]> ? K_7 : never : never }[keyof S] | { [K_8 in keyof S]: S[K_8] extends _$_sinclair_typebox0.TReadonly<TSchema> ? S[K_8] extends _$_sinclair_typebox0.TOptional<S[K_8]> ? never : K_8 : never }[keyof S] | { [K_9 in keyof S]: S[K_9] extends _$_sinclair_typebox0.TOptional<TSchema> ? S[K_9] extends _$_sinclair_typebox0.TReadonly<S[K_9]> ? never : K_9 : never }[keyof S]>>>> : Record<string, never> : Record<string, never>)[F];
1060
1087
  }, index: number) => React.ReactNode;
1061
1088
  }) => _$react_jsx_runtime0.JSX.Element;
1062
1089
  useSetting: <K extends keyof (TSettingsShape extends Record<string, never> ? Record<string, never> : _$_sinclair_typebox0.Evaluate<Readonly<Partial<Pick<{ [K_1 in keyof TSettingsShape]: (TSettingsShape[K_1] & {
@@ -67,6 +67,7 @@ function buildInitialSeeds(properties, parentTempId, content, allSeeds, counter)
67
67
  if (propSchema.type === "array" && propSchema.items?.properties) continue;
68
68
  if ("default" in propSchema) itemContent[propName] = propSchema.default;
69
69
  }
70
+ const itemSettingsDefaults = fieldSchema.defaultItemSettings;
70
71
  const markers = [];
71
72
  let prevPosition = null;
72
73
  for (let i = 0; i < defaultCount; i++) {
@@ -78,6 +79,7 @@ function buildInitialSeeds(properties, parentTempId, content, allSeeds, counter)
78
79
  parentTempId,
79
80
  fieldName,
80
81
  content: { ...itemContent },
82
+ settings: itemSettingsDefaults ? { ...itemSettingsDefaults } : void 0,
81
83
  position
82
84
  });
83
85
  markers.push({ _itemId: tempId });
@@ -102,6 +104,7 @@ function buildPeekItems(properties, blockId, parentItemId, content, allItems, co
102
104
  if (propSchema.type === "array" && propSchema.items?.properties) continue;
103
105
  if ("default" in propSchema) itemContent[propName] = propSchema.default;
104
106
  }
107
+ const itemSettingsDefaults = fieldSchema.defaultItemSettings;
105
108
  const markers = [];
106
109
  let prevPosition = null;
107
110
  for (let i = 0; i < defaultCount; i++) {
@@ -114,6 +117,7 @@ function buildPeekItems(properties, blockId, parentItemId, content, allItems, co
114
117
  parentItemId,
115
118
  fieldName,
116
119
  content: { ...itemContent },
120
+ settings: itemSettingsDefaults ? { ...itemSettingsDefaults } : null,
117
121
  summary: "",
118
122
  position,
119
123
  createdAt: 0,
@@ -139,7 +143,7 @@ function createBlock(options) {
139
143
  description: options.description,
140
144
  properties: typeboxSchema.properties,
141
145
  required: Object.keys(options.content),
142
- toMarkdown: resolveToMarkdown(options.toMarkdown)
146
+ toMarkdown: resolveToMarkdown(options.toMarkdown, options.settings, "block")
143
147
  };
144
148
  const settingsTypeboxSchema = options.settings ? Type$1.Object(options.settings) : null;
145
149
  const settingsSchema = settingsTypeboxSchema ? {
@@ -157,12 +161,14 @@ function createBlock(options) {
157
161
  contentDefaultsForStorage[key] = prop.default;
158
162
  }
159
163
  const repeatableItemDefaults = {};
164
+ const repeatableItemSettingsDefaults = {};
160
165
  for (const [key, prop] of Object.entries(typeboxSchema.properties)) {
161
166
  const p = prop;
162
167
  if (p.type === "array" && p.items?.properties) {
163
168
  const itemDefaults = {};
164
169
  for (const [itemKey, itemProp] of Object.entries(p.items.properties)) if (itemProp && typeof itemProp === "object" && "default" in itemProp) itemDefaults[itemKey] = itemProp.default;
165
170
  if (Object.keys(itemDefaults).length > 0) repeatableItemDefaults[key] = itemDefaults;
171
+ if (p.defaultItemSettings && typeof p.defaultItemSettings === "object") repeatableItemSettingsDefaults[key] = p.defaultItemSettings;
166
172
  }
167
173
  }
168
174
  const settingsDefaults = {};
@@ -761,7 +767,9 @@ function createBlock(options) {
761
767
  const repeaterContext = React.use(RepeaterItemContext);
762
768
  const { filesMap } = useNormalizedData();
763
769
  const rawSource = repeaterContext ? repeaterContext.itemContent[name] : content[name];
764
- const fieldValue = (isFileMarker(rawSource) ? resolveFileMarker(rawSource, filesMap) : rawSource) ?? contentDefaults[String(name)];
770
+ const rawValue = isFileMarker(rawSource) ? resolveFileMarker(rawSource, filesMap) : rawSource;
771
+ const defaultValue = repeaterContext ? repeatableItemDefaults[repeaterContext.arrayFieldName]?.[String(name)] : contentDefaults[String(name)];
772
+ const fieldValue = rawValue ?? defaultValue;
765
773
  const t1 = String(name);
766
774
  let t2;
767
775
  if ($[0] !== blockId || $[1] !== repeaterContext || $[2] !== t1) {
@@ -870,7 +878,7 @@ function createBlock(options) {
870
878
  return t14;
871
879
  };
872
880
  const File = (t0) => {
873
- const $ = c(7);
881
+ const $ = c(8);
874
882
  const { name, children } = t0;
875
883
  const blockContext = React.use(Context);
876
884
  if (!blockContext) throw new Error("File must be used within a Block Component");
@@ -879,8 +887,10 @@ function createBlock(options) {
879
887
  const { filesMap } = useNormalizedData();
880
888
  const rawSource = repeaterContext ? repeaterContext.itemContent[name] : content[name];
881
889
  let t1;
882
- if ($[0] !== children || $[1] !== filesMap || $[2] !== name || $[3] !== rawSource) {
883
- const fieldValue = (isFileMarker(rawSource) ? resolveFileMarker(rawSource, filesMap) : rawSource) ?? contentDefaults[String(name)];
890
+ if ($[0] !== children || $[1] !== filesMap || $[2] !== name || $[3] !== rawSource || $[4] !== repeaterContext) {
891
+ const rawValue = isFileMarker(rawSource) ? resolveFileMarker(rawSource, filesMap) : rawSource;
892
+ const defaultValue = repeaterContext ? repeatableItemDefaults[repeaterContext.arrayFieldName]?.[String(name)] : contentDefaults[String(name)];
893
+ const fieldValue = rawValue ?? defaultValue;
884
894
  t1 = children({
885
895
  href: fieldValue.url,
886
896
  download: fieldValue.filename
@@ -889,14 +899,15 @@ function createBlock(options) {
889
899
  $[1] = filesMap;
890
900
  $[2] = name;
891
901
  $[3] = rawSource;
892
- $[4] = t1;
893
- } else t1 = $[4];
902
+ $[4] = repeaterContext;
903
+ $[5] = t1;
904
+ } else t1 = $[5];
894
905
  let t2;
895
- if ($[5] !== t1) {
906
+ if ($[6] !== t1) {
896
907
  t2 = /* @__PURE__ */ jsx(Fragment, { children: t1 });
897
- $[5] = t1;
898
- $[6] = t2;
899
- } else t2 = $[6];
908
+ $[6] = t1;
909
+ $[7] = t2;
910
+ } else t2 = $[7];
900
911
  return t2;
901
912
  };
902
913
  const RepeaterItemWrapper = (t0) => {
@@ -968,92 +979,141 @@ function createBlock(options) {
968
979
  return t3;
969
980
  };
970
981
  const Repeater = (t0) => {
971
- const $ = c(10);
982
+ const $ = c(28);
972
983
  const { name, children } = t0;
973
984
  const blockContext = React.use(Context);
974
985
  if (!blockContext) throw new Error("Repeater must be used within a Block Component");
975
986
  const { blockId, content, mode } = blockContext;
976
987
  const parentRepeaterContext = React.use(RepeaterItemContext);
977
988
  const fieldName = String(name);
978
- const itemComponents = {
979
- Field,
980
- Link,
981
- Embed,
982
- Image,
983
- File,
984
- Repeater
985
- };
989
+ const ItemField = Field;
990
+ const ItemLink = Link;
991
+ const ItemEmbed = Embed;
992
+ const ItemImage = Image;
993
+ const ItemFile = File;
994
+ const ItemRepeater = Repeater;
986
995
  const source = parentRepeaterContext ? parentRepeaterContext.itemContent[name] : content[name];
987
996
  const { itemsMap } = useNormalizedData();
988
- let arrayValue = source ?? [];
989
- if (!Array.isArray(arrayValue)) throw new Error(`Field "${String(name)}" is not an array`);
997
+ let T0;
990
998
  let t1;
991
- if ($[0] !== itemsMap) {
992
- t1 = (item) => {
993
- if (isItemMarker(item)) return itemsMap.get(item._itemId) ?? null;
994
- return item;
995
- };
996
- $[0] = itemsMap;
997
- $[1] = t1;
998
- } else t1 = $[1];
999
- arrayValue = arrayValue.map(t1).filter(Boolean);
1000
- if (arrayValue.length === 0) {
1001
- const fieldSchema = parentRepeaterContext ? typeboxSchema.properties[parentRepeaterContext.arrayFieldName]?.items?.properties?.[fieldName] : typeboxSchema.properties[fieldName];
1002
- const ait = fieldSchema?.arrayItemType;
1003
- if (ait === "Image" || ait === "File") {
1004
- const defaultCount = fieldSchema.defaultItems ?? 0;
1005
- const itemProps = fieldSchema.items?.properties;
1006
- if (defaultCount > 0 && itemProps) {
1007
- let t2;
1008
- if ($[2] !== defaultCount || $[3] !== itemProps) {
1009
- const itemContent = {};
1010
- for (const [propName, propSchema] of Object.entries(itemProps)) if (propSchema && typeof propSchema === "object" && "default" in propSchema) itemContent[propName] = propSchema.default;
1011
- t2 = Array.from({ length: defaultCount }, () => ({ ...itemContent }));
1012
- $[2] = defaultCount;
1013
- $[3] = itemProps;
1014
- $[4] = t2;
1015
- } else t2 = $[4];
1016
- arrayValue = t2;
999
+ let t2;
1000
+ let t3;
1001
+ if ($[0] !== blockId || $[1] !== children || $[2] !== fieldName || $[3] !== itemsMap || $[4] !== mode || $[5] !== name || $[6] !== parentRepeaterContext || $[7] !== source) {
1002
+ let arrayValue = source ?? [];
1003
+ if (!Array.isArray(arrayValue)) throw new Error(`Field "${String(name)}" is not an array`);
1004
+ let t4;
1005
+ if ($[12] !== itemsMap) {
1006
+ t4 = (item) => {
1007
+ if (isItemMarker(item)) return itemsMap.get(item._itemId) ?? null;
1008
+ return item;
1009
+ };
1010
+ $[12] = itemsMap;
1011
+ $[13] = t4;
1012
+ } else t4 = $[13];
1013
+ arrayValue = arrayValue.map(t4).filter(Boolean);
1014
+ if (arrayValue.length === 0) {
1015
+ const fieldSchema = parentRepeaterContext ? typeboxSchema.properties[parentRepeaterContext.arrayFieldName]?.items?.properties?.[fieldName] : typeboxSchema.properties[fieldName];
1016
+ const ait = fieldSchema?.arrayItemType;
1017
+ if (ait === "Image" || ait === "File") {
1018
+ const defaultCount = fieldSchema.defaultItems ?? 0;
1019
+ const itemProps = fieldSchema.items?.properties;
1020
+ if (defaultCount > 0 && itemProps) {
1021
+ let t5;
1022
+ if ($[14] !== defaultCount || $[15] !== itemProps) {
1023
+ const itemContent = {};
1024
+ for (const [propName, propSchema] of Object.entries(itemProps)) if (propSchema && typeof propSchema === "object" && "default" in propSchema) itemContent[propName] = propSchema.default;
1025
+ t5 = Array.from({ length: defaultCount }, () => ({ ...itemContent }));
1026
+ $[14] = defaultCount;
1027
+ $[15] = itemProps;
1028
+ $[16] = t5;
1029
+ } else t5 = $[16];
1030
+ arrayValue = t5;
1031
+ }
1017
1032
  }
1018
1033
  }
1034
+ const settingsDefaultsForField = repeatableItemSettingsDefaults[fieldName];
1035
+ T0 = RepeaterHoverProvider;
1036
+ t1 = blockId;
1037
+ t2 = fieldName;
1038
+ let t5;
1039
+ if ($[17] !== blockId || $[18] !== children || $[19] !== fieldName || $[20] !== mode || $[21] !== settingsDefaultsForField) {
1040
+ t5 = (item_0, index) => {
1041
+ const isDbItem = item_0.content !== void 0 && item_0.id != null;
1042
+ const itemContent_0 = {
1043
+ ...repeatableItemDefaults[fieldName],
1044
+ ...isDbItem ? item_0.content : item_0
1045
+ };
1046
+ const itemSettings = {
1047
+ ...settingsDefaultsForField,
1048
+ ...(isDbItem ? item_0.settings : null) ?? {}
1049
+ };
1050
+ const itemId = isDbItem ? item_0.id : void 0;
1051
+ const useItemSetting = (settingName) => itemSettings[settingName];
1052
+ const itemApi = {
1053
+ Field: ItemField,
1054
+ Link: ItemLink,
1055
+ Embed: ItemEmbed,
1056
+ Image: ItemImage,
1057
+ File: ItemFile,
1058
+ Repeater: ItemRepeater,
1059
+ useSetting: useItemSetting
1060
+ };
1061
+ return /* @__PURE__ */ jsx(RepeaterItemContext.Provider, {
1062
+ value: {
1063
+ arrayFieldName: fieldName,
1064
+ itemIndex: index,
1065
+ itemContent: itemContent_0,
1066
+ itemSettings,
1067
+ itemId
1068
+ },
1069
+ children: /* @__PURE__ */ jsx(RepeaterItemWrapper, {
1070
+ itemId,
1071
+ blockId,
1072
+ mode,
1073
+ children: children(itemApi, index)
1074
+ })
1075
+ }, itemId ?? index);
1076
+ };
1077
+ $[17] = blockId;
1078
+ $[18] = children;
1079
+ $[19] = fieldName;
1080
+ $[20] = mode;
1081
+ $[21] = settingsDefaultsForField;
1082
+ $[22] = t5;
1083
+ } else t5 = $[22];
1084
+ t3 = arrayValue.map(t5);
1085
+ $[0] = blockId;
1086
+ $[1] = children;
1087
+ $[2] = fieldName;
1088
+ $[3] = itemsMap;
1089
+ $[4] = mode;
1090
+ $[5] = name;
1091
+ $[6] = parentRepeaterContext;
1092
+ $[7] = source;
1093
+ $[8] = T0;
1094
+ $[9] = t1;
1095
+ $[10] = t2;
1096
+ $[11] = t3;
1097
+ } else {
1098
+ T0 = $[8];
1099
+ t1 = $[9];
1100
+ t2 = $[10];
1101
+ t3 = $[11];
1019
1102
  }
1020
- const T0 = RepeaterHoverProvider;
1021
- const t2 = arrayValue.map((item_0, index) => {
1022
- const isDbItem = item_0.content !== void 0 && item_0.id != null;
1023
- const itemContent_0 = {
1024
- ...repeatableItemDefaults[fieldName],
1025
- ...isDbItem ? item_0.content : item_0
1026
- };
1027
- const itemId = isDbItem ? item_0.id : void 0;
1028
- return /* @__PURE__ */ jsx(RepeaterItemContext.Provider, {
1029
- value: {
1030
- arrayFieldName: fieldName,
1031
- itemIndex: index,
1032
- itemContent: itemContent_0,
1033
- itemId
1034
- },
1035
- children: /* @__PURE__ */ jsx(RepeaterItemWrapper, {
1036
- itemId,
1037
- blockId,
1038
- mode,
1039
- children: children(itemComponents, index)
1040
- })
1041
- }, itemId ?? index);
1042
- });
1043
- let t3;
1044
- if ($[5] !== T0 || $[6] !== blockId || $[7] !== fieldName || $[8] !== t2) {
1045
- t3 = /* @__PURE__ */ jsx(T0, {
1046
- blockId,
1047
- fieldName,
1048
- children: t2
1103
+ let t4;
1104
+ if ($[23] !== T0 || $[24] !== t1 || $[25] !== t2 || $[26] !== t3) {
1105
+ t4 = /* @__PURE__ */ jsx(T0, {
1106
+ blockId: t1,
1107
+ fieldName: t2,
1108
+ children: t3
1049
1109
  });
1050
- $[5] = T0;
1051
- $[6] = blockId;
1052
- $[7] = fieldName;
1053
- $[8] = t2;
1054
- $[9] = t3;
1055
- } else t3 = $[9];
1056
- return t3;
1110
+ $[23] = T0;
1111
+ $[24] = t1;
1112
+ $[25] = t2;
1113
+ $[26] = t3;
1114
+ $[27] = t4;
1115
+ } else t4 = $[27];
1116
+ return t4;
1057
1117
  };
1058
1118
  const BlockComponent = (t0) => {
1059
1119
  const $ = c(69);
@@ -1,5 +1,5 @@
1
1
  import * as _$_sinclair_typebox0 from "@sinclair/typebox";
2
- import { TArray, TObject, TSchema, TUnsafe } from "@sinclair/typebox";
2
+ import { Static, TArray, TObject, TSchema, TUnsafe } from "@sinclair/typebox";
3
3
 
4
4
  //#region src/core/lib/contentType.d.ts
5
5
  declare class FieldToken {
@@ -7,12 +7,40 @@ declare class FieldToken {
7
7
  constructor(fieldName: string);
8
8
  toString(): string;
9
9
  }
10
+ type SettingsScope = "block" | "item";
11
+ /**
12
+ * Serializable conditional block produced by the settings proxy. Emits Handlebars-style
13
+ * `{{#if ...}}...{{/if}}` syntax wrapping each child line, tagged with its scope so the
14
+ * server-side resolver knows whether to read from `settings` or `itemSettings`.
15
+ */
16
+ declare class Conditional {
17
+ readonly scope: SettingsScope;
18
+ readonly settingName: string;
19
+ readonly enumValue: string | null;
20
+ readonly children: ReadonlyArray<string | FieldToken | Conditional>;
21
+ constructor(scope: SettingsScope, settingName: string, enumValue: string | null, children: ReadonlyArray<string | FieldToken | Conditional>);
22
+ get openTag(): string;
23
+ get closeTag(): string;
24
+ }
25
+ type ConditionalChild = string | FieldToken | Conditional;
26
+ type ConditionalLines = ConditionalChild | ReadonlyArray<ConditionalChild>;
10
27
  type ContentProxy<TShape extends Record<string, TSchema>> = { [K in keyof TShape & string]: FieldToken };
11
- type ToMarkdownBuilder<TShape extends Record<string, TSchema>> = (c: ContentProxy<TShape>) => ReadonlyArray<string | FieldToken>;
28
+ /**
29
+ * Callable shape for one entry on the settings proxy. Booleans take a single `lines`
30
+ * argument; enums take `(value, lines)`. Settings of other shapes are disallowed — they
31
+ * don't make sense as conditions.
32
+ */
33
+ type SettingCallable<T extends TSchema> = Static<T> extends boolean ? (lines: ConditionalLines) => Conditional : Static<T> extends string ? (value: Static<T>, lines: ConditionalLines) => Conditional : never;
34
+ type SettingsProxy<TShape extends Record<string, TSchema>> = { [K in keyof TShape & string]: SettingCallable<TShape[K]> };
35
+ type ToMarkdownBuilder<TContent extends Record<string, TSchema>, TSettings extends Record<string, TSchema> = Record<string, never>> = (c: ContentProxy<TContent>, s: SettingsProxy<TSettings>) => ReadonlyArray<string | FieldToken | Conditional>;
12
36
  declare const EmbedURLBrand: unique symbol;
13
37
  type EmbedURL = string & {
14
38
  readonly [EmbedURLBrand]: true;
15
39
  };
40
+ declare const ItemSettingsBrand: unique symbol;
41
+ type WithItemSettings<S extends Record<string, TSchema>> = {
42
+ readonly [ItemSettingsBrand]?: S;
43
+ };
16
44
  declare const LinkBrand: unique symbol;
17
45
  type LinkValue = ({
18
46
  type: "external";
@@ -91,25 +119,33 @@ declare const Type$1: {
91
119
  * Creates a repeatable array of object items.
92
120
  * The default array is auto-generated based on minItems.
93
121
  *
122
+ * Items may also declare per-item `settings` (Enum/Boolean only) — not
123
+ * inline-editable; they appear in the sidebar when the item is selected,
124
+ * similar to block-level settings.
125
+ *
94
126
  * @example
95
127
  * Type.RepeatableItem({
96
128
  * content: {
97
129
  * title: Type.String({ default: 'Item' }),
98
130
  * description: Type.String({ default: 'Description' }),
99
131
  * },
132
+ * settings: {
133
+ * highlighted: Type.Boolean({ default: false, title: 'Highlighted' }),
134
+ * },
100
135
  * minItems: 1,
101
136
  * maxItems: 10,
102
137
  * title: 'Items',
103
138
  * toMarkdown: (c) => [`### ${c.title}`, c.description],
104
139
  * })
105
140
  */
106
- RepeatableItem: <T extends Record<string, TSchema>>(options: {
141
+ RepeatableItem: <T extends Record<string, TSchema>, S extends Record<string, TSchema> = Record<string, never>>(options: {
107
142
  content: T;
143
+ settings?: S;
108
144
  minItems: number;
109
145
  maxItems: number;
110
146
  title?: string;
111
- toMarkdown: ToMarkdownBuilder<T>;
112
- }) => TArray<TObject<T>>;
147
+ toMarkdown: ToMarkdownBuilder<T, S>;
148
+ }) => TArray<TObject<T>> & WithItemSettings<S>;
113
149
  /**
114
150
  * Creates an enum field with a set of predefined options.
115
151
  *
@@ -120,11 +156,11 @@ declare const Type$1: {
120
156
  * title: 'Alignment'
121
157
  * })
122
158
  */
123
- Enum: (options: {
124
- default: string;
125
- options: Record<string, string>;
159
+ Enum: <const O extends Record<string, string>>(options: {
160
+ default: keyof O & string;
161
+ options: O;
126
162
  title?: string;
127
- }) => TUnsafe<string>;
163
+ }) => TUnsafe<keyof O & string>;
128
164
  /**
129
165
  * Creates a boolean toggle field.
130
166
  *
@@ -169,4 +205,4 @@ declare const Type$1: {
169
205
  File: typeof _fileType;
170
206
  };
171
207
  //#endregion
172
- export { EmbedURL, FileValue, ImageValue, LinkValue, ToMarkdownBuilder, Type$1 as Type };
208
+ export { EmbedURL, FileValue, ImageValue, ItemSettingsBrand, LinkValue, ToMarkdownBuilder, Type$1 as Type };
@@ -9,14 +9,55 @@ var FieldToken = class {
9
9
  return `{{${this.fieldName}}}`;
10
10
  }
11
11
  };
12
+ /**
13
+ * Serializable conditional block produced by the settings proxy. Emits Handlebars-style
14
+ * `{{#if ...}}...{{/if}}` syntax wrapping each child line, tagged with its scope so the
15
+ * server-side resolver knows whether to read from `settings` or `itemSettings`.
16
+ */
17
+ var Conditional = class {
18
+ constructor(scope, settingName, enumValue, children) {
19
+ this.scope = scope;
20
+ this.settingName = settingName;
21
+ this.enumValue = enumValue;
22
+ this.children = children;
23
+ }
24
+ get openTag() {
25
+ const root = this.scope === "block" ? "settings" : "itemSettings";
26
+ if (this.enumValue === null) return `{{#if ${root}.${this.settingName}}}`;
27
+ return `{{#if (eq ${root}.${this.settingName} "${this.enumValue}")}}`;
28
+ }
29
+ get closeTag() {
30
+ return "{{/if}}";
31
+ }
32
+ };
12
33
  function createContentProxy() {
13
34
  return new Proxy({}, { get(_target, prop) {
14
35
  if (typeof prop !== "string") return void 0;
15
36
  return new FieldToken(prop);
16
37
  } });
17
38
  }
18
- function resolveToMarkdown(builder) {
19
- return builder(createContentProxy()).map((entry) => entry instanceof FieldToken ? entry.toString() : String(entry));
39
+ function createSettingsProxy(settingsShape, scope) {
40
+ return new Proxy({}, { get(_target, prop) {
41
+ if (typeof prop !== "string") return void 0;
42
+ const fieldType = (settingsShape?.[prop])?.fieldType;
43
+ if (fieldType === "Boolean") return (lines) => new Conditional(scope, prop, null, Array.isArray(lines) ? lines : [lines]);
44
+ if (fieldType === "Enum") return (value, lines) => new Conditional(scope, prop, value, Array.isArray(lines) ? lines : [lines]);
45
+ throw new Error(`toMarkdown settings proxy: "${prop}" is not a Boolean or Enum setting on this ${scope}.`);
46
+ } });
47
+ }
48
+ /** Flatten a `Conditional`'s children into wrapped lines, recursing into nested Conditionals. */
49
+ function serializeConditional(cond) {
50
+ const out = [];
51
+ for (const child of cond.children) if (child instanceof Conditional) for (const nested of serializeConditional(child)) out.push(`${cond.openTag}${nested}${cond.closeTag}`);
52
+ else out.push(`${cond.openTag}${String(child)}${cond.closeTag}`);
53
+ return out;
54
+ }
55
+ function resolveToMarkdown(builder, settingsShape, scope) {
56
+ const entries = builder(createContentProxy(), createSettingsProxy(settingsShape, scope));
57
+ const out = [];
58
+ for (const entry of entries) if (entry instanceof Conditional) out.push(...serializeConditional(entry));
59
+ else out.push(entry instanceof FieldToken ? entry.toString() : String(entry));
60
+ return out;
20
61
  }
21
62
  function _imageType(options) {
22
63
  const imageDefault = {
@@ -102,13 +143,25 @@ const Type$1 = {
102
143
  const defaultItem = {};
103
144
  for (const [key, prop] of Object.entries(objectSchema.properties)) if ("default" in prop) defaultItem[key] = prop.default;
104
145
  const defaultArray = Array(options.minItems).fill(null).map(() => ({ ...defaultItem }));
146
+ const settingsTypeboxSchema = options.settings ? Type.Object(options.settings) : null;
147
+ const itemSettingsSchema = settingsTypeboxSchema ? {
148
+ type: "object",
149
+ properties: settingsTypeboxSchema.properties,
150
+ required: Object.keys(options.settings)
151
+ } : void 0;
152
+ const defaultItemSettings = {};
153
+ if (settingsTypeboxSchema) {
154
+ for (const [key, prop] of Object.entries(settingsTypeboxSchema.properties)) if ("default" in prop) defaultItemSettings[key] = prop.default;
155
+ }
105
156
  return Type.Array(objectSchema, {
106
157
  minItems: options.minItems,
107
158
  maxItems: options.maxItems,
108
159
  default: defaultArray,
109
160
  title: options.title,
110
161
  fieldType: "RepeatableItem",
111
- toMarkdown: resolveToMarkdown(options.toMarkdown)
162
+ toMarkdown: resolveToMarkdown(options.toMarkdown, options.settings, "item"),
163
+ itemSettingsSchema,
164
+ defaultItemSettings: settingsTypeboxSchema ? defaultItemSettings : void 0
112
165
  });
113
166
  },
114
167
  Enum: (options) => {
@@ -254,7 +254,7 @@ const AddBlockSheet = () => {
254
254
  } else t15 = $[30];
255
255
  const t16 = "flex-1 overflow-auto p-2";
256
256
  const T1 = Command;
257
- const t17 = "bg-background overflow-visible";
257
+ const t17 = "overflow-visible";
258
258
  const t18 = _temp7;
259
259
  let t19;
260
260
  if ($[31] === Symbol.for("react.memo_cache_sentinel")) {
@@ -286,10 +286,13 @@ const AddBlockSheet = () => {
286
286
  handleAddBlock(block_3);
287
287
  },
288
288
  className: "group flex items-center justify-between gap-2",
289
- children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("span", { children: block_3._internal.title }), /* @__PURE__ */ jsx("span", {
290
- className: "text-muted-foreground block",
291
- children: displayCount(block_3._internal.id)
292
- })] }), /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
289
+ children: [/* @__PURE__ */ jsxs("div", {
290
+ className: "flex-1",
291
+ children: [/* @__PURE__ */ jsx("span", { children: block_3._internal.title }), /* @__PURE__ */ jsx("span", {
292
+ className: "text-muted-foreground block",
293
+ children: displayCount(block_3._internal.id)
294
+ })]
295
+ }), /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
293
296
  className: "hidden group-focus-within:flex group-hover:flex",
294
297
  children: /* @__PURE__ */ jsx(InfoIcon, {})
295
298
  }), /* @__PURE__ */ jsx(TooltipContent, {
@@ -20,7 +20,7 @@ const AgentChatSheet = () => {
20
20
  className: "flex flex-1 items-center justify-center p-6",
21
21
  children: /* @__PURE__ */ jsx("p", {
22
22
  className: "text-muted-foreground text-center text-sm",
23
- children: "Coming soon"
23
+ children: "Coming soon: MCP server and integrated chat"
24
24
  })
25
25
  });
26
26
  $[1] = t1;