@valbuild/react 0.125.0 → 0.127.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/CHANGELOG.md CHANGED
@@ -1,5 +1,137 @@
1
1
  # @valbuild/react
2
2
 
3
+ ## 0.127.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#608](https://github.com/valbuild/val/pull/608) [`5b7fe05`](https://github.com/valbuild/val/commit/5b7fe05cec6365f9cd1de9ba31e65ed4a87edb63) Thanks [@freekh](https://github.com/freekh)! - `s.locale()`: one of the project's languages.
8
+
9
+ The languages themselves are declared in the settings module (`locales.available`);
10
+ this says that a value is one of them.
11
+
12
+ ```typescript
13
+ // a field: everything in this entry is in this language
14
+ s.record(s.string(), s.object({ locale: s.locale(), title: s.string() }));
15
+
16
+ // a key: one entry per language
17
+ s.record(s.locale(), s.object({ title: s.string() }));
18
+ ```
19
+
20
+ Every locale in content is checked against the project's list, the way `keyOf`
21
+ and `route` are checked against what they point at. An undeclared language names
22
+ the ones the project has; a project that has declared none is told to declare
23
+ them rather than told the value is wrong.
24
+
25
+ A locale is stored as the tag itself — the value in content is `nb-NO`, and a
26
+ record keyed by `s.locale()` has `nb-NO` as its key. Spelling one differently
27
+ where it is stored (`/no/…` as a URL segment) is a real need and is deliberately
28
+ not in this release: it changes what is accepted as well as what is shown, so it
29
+ is being designed on its own rather than folded in here.
30
+
31
+ A locale is **never stega encoded**: it ends up in `<html lang>`, in `hreflang`
32
+ and in `Intl` constructors, none of which survive invisible characters.
33
+
34
+ `assistant.translation` joins the settings module alongside `context` and `tone`
35
+ — a note per language, keyed by language, so only the target language's rules are
36
+ sent when translating into it.
37
+
38
+ ### Patch Changes
39
+
40
+ - Updated dependencies [[`7fa8699`](https://github.com/valbuild/val/commit/7fa869974bc895af992a7d5c18b76253636d7d65), [`600308d`](https://github.com/valbuild/val/commit/600308d0174990ad9f5c417147d160273489c65a), [`5b7fe05`](https://github.com/valbuild/val/commit/5b7fe05cec6365f9cd1de9ba31e65ed4a87edb63), [`88262ac`](https://github.com/valbuild/val/commit/88262ac8db068650a664981ef73556457d87741a), [`7072e07`](https://github.com/valbuild/val/commit/7072e07623c953a09ac14388ae22dada0b431ce3), [`29811c3`](https://github.com/valbuild/val/commit/29811c3f8c7e001a950e6f4833af6888e6a4efea), [`9983116`](https://github.com/valbuild/val/commit/99831164c5151aad7ca69de79e1d0d59878be251)]:
41
+ - @valbuild/core@0.127.0
42
+ - @valbuild/shared@0.127.0
43
+ - @valbuild/ui@0.127.0
44
+
45
+ ## 0.126.0
46
+
47
+ ### Minor Changes
48
+
49
+ - [#652](https://github.com/valbuild/val/pull/652) [`f2fe70d`](https://github.com/valbuild/val/commit/f2fe70dab2b65000dfaf289f09c70b4a8291467a) Thanks [@freekh](https://github.com/freekh)! - `s.union` is now `s.discriminatedUnion` and `s.enum`.
50
+
51
+ `s.union` did two unrelated jobs and worked out which one you meant from its
52
+ first argument: a string key meant a tagged union of objects, literal schemas
53
+ meant a set of allowed strings. Those are now two schemas with two names.
54
+
55
+ ```ts
56
+ // A fixed set of strings — presents as a dropdown
57
+ s.enum("primary", "secondary", "ghost"); // Schema<"primary" | "secondary" | "ghost">
58
+
59
+ // One of several object shapes, told apart by a tag field
60
+ s.discriminatedUnion(
61
+ "type",
62
+ s.object({ type: s.literal("hero"), heading: s.string() }),
63
+ s.object({ type: s.literal("quote"), text: s.string() }),
64
+ );
65
+ ```
66
+
67
+ `s.enum` takes the strings directly, so the `s.literal(...)` wrapper is gone.
68
+
69
+ **`s.union` still works** — it is deprecated, and it builds exactly the schema
70
+ above, so nothing has to change today:
71
+
72
+ ```ts
73
+ s.union(s.literal("one"), s.literal("two")); // → s.enum("one", "two")
74
+ s.union("type", pageA, pageB); // → s.discriminatedUnion("type", pageA, pageB)
75
+ ```
76
+
77
+ The two are different kinds of node, and that is the reason for the split. A
78
+ discriminated union is a container: the selected variant's fields are the fields
79
+ being edited, and everything that walks a schema descends through it. An enum is
80
+ a leaf — a string with a closed domain — so nothing recurses into it. Told apart
81
+ only by the shape of `key`, every consumer had to re-derive which one it was
82
+ holding; each now has its own serialized type (`"discriminated-union"` and
83
+ `"enum"`) and Val Studio has a field per kind rather than one field that
84
+ branches.
85
+
86
+ Two behaviour changes fall out of the split, both of them fixes:
87
+
88
+ - A value that is not a string at all now fails an enum's validation with a
89
+ type error. `s.union` of literals only ever checked the value against its
90
+ literals when the value WAS a string, so a number or an object where an enum
91
+ was declared validated clean.
92
+ - An enum field now shows its validation errors in Val Studio where the field
93
+ is opened on its own — the module editor and the canvas's fields column — and
94
+ gets the compact error layout inside an inline list row. It is a leaf now, so
95
+ it goes through the same error rendering as every other leaf field; the string
96
+ union bypassed it and showed nothing in those places.
97
+
98
+ Several latent crashes in the old `s.union` are fixed on the way past, all of
99
+ them cases where it threw a `TypeError` instead of reporting:
100
+
101
+ - A required discriminated union holding `null` now reports a type error rather
102
+ than throwing, and resolving a path underneath a nullable one that is `null`
103
+ gives the error the API promises instead of a crash.
104
+ - `s.literal("")` is a legal discriminator tag, and `s.enum("")` a legal value.
105
+ Both used to be treated as absent by a truthiness check — in path resolution,
106
+ in stega encoding, and in the message that lists a union's valid tags. The
107
+ editor's dropdowns handle them too: an empty value is reserved by the select
108
+ component and had to be mapped around.
109
+ - A variant that omits the discriminator entirely is now reported as the schema
110
+ error it is, instead of throwing while the check looked for it.
111
+ - An enum's value is now indexed for search, like every other string leaf. The
112
+ old string union was never indexed at all, so searching for one of its values
113
+ could not find the field.
114
+ - A nullable discriminated union set to `null` no longer renders a spinner that
115
+ never resolves.
116
+
117
+ `s.discriminatedUnion` also requires at least one variant, as `s.enum` requires
118
+ at least one value: a union with nothing to select is not a thing to write, and
119
+ everything downstream reads the first variant where it needs any.
120
+
121
+ If you read serialized schemas yourself, that is the breaking part: `type` is no
122
+ longer `"union"`, an enum carries `values: string[]` instead of a `key` plus
123
+ `items` of literal schemas, and `UnionSchema` is no longer a class.
124
+ `SerializedUnionSchema`, `SerializedStringUnionSchema`,
125
+ `SerializedObjectUnionSchema` and `UnionSchema` remain as deprecated type
126
+ aliases.
127
+
128
+ ### Patch Changes
129
+
130
+ - Updated dependencies [[`719ad6b`](https://github.com/valbuild/val/commit/719ad6b607bcf136d0dbde9e90bf4b8a843561a4), [`9830277`](https://github.com/valbuild/val/commit/9830277e9aaca8da3030f629c2656ec58da47e45), [`64bfd0a`](https://github.com/valbuild/val/commit/64bfd0a6c85832ea5169b53e47087f22e193df36), [`7782979`](https://github.com/valbuild/val/commit/7782979e9b52f2015a6e72dc981e630d4f8c78e2), [`5bfd630`](https://github.com/valbuild/val/commit/5bfd630b63dee2189e238f20fe72ecc5537160f7), [`ccbcda6`](https://github.com/valbuild/val/commit/ccbcda60b3e3c465071229ae1ba28ac735483e63), [`f2fe70d`](https://github.com/valbuild/val/commit/f2fe70dab2b65000dfaf289f09c70b4a8291467a), [`755e1a3`](https://github.com/valbuild/val/commit/755e1a3953775cb8d2c2dce87d6810d3dc329640), [`c6b1ec8`](https://github.com/valbuild/val/commit/c6b1ec84f1883750a4cfe5f70470b177621e971f), [`656f680`](https://github.com/valbuild/val/commit/656f680043c640f678625a64e690389ab23a0a69), [`610a041`](https://github.com/valbuild/val/commit/610a0414b120b521f38a2eb1182b3778bf778b2b), [`171208a`](https://github.com/valbuild/val/commit/171208a20177e68ed5a8b1a6fdaabfe893a6aa5f)]:
131
+ - @valbuild/ui@0.126.0
132
+ - @valbuild/shared@0.126.0
133
+ - @valbuild/core@0.126.0
134
+
3
135
  ## 0.125.0
4
136
 
5
137
  ### Patch Changes
@@ -124,22 +124,6 @@ function _objectSpread2(e) {
124
124
  return e;
125
125
  }
126
126
 
127
- function _arrayWithoutHoles(r) {
128
- if (Array.isArray(r)) return slicedToArray._arrayLikeToArray(r);
129
- }
130
-
131
- function _iterableToArray(r) {
132
- if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
133
- }
134
-
135
- function _nonIterableSpread() {
136
- throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
137
- }
138
-
139
- function _toConsumableArray(r) {
140
- return _arrayWithoutHoles(r) || _iterableToArray(r) || slicedToArray._unsupportedIterableToArray(r) || _nonIterableSpread();
141
- }
142
-
143
127
  /**
144
128
  * ValEncodedString is a string that is encoded using steganography.
145
129
  *
@@ -161,19 +145,18 @@ function _toConsumableArray(r) {
161
145
  **/
162
146
 
163
147
  /**
164
- * Resolves the matching sub-schema for a tagged union based on the discriminator key.
148
+ * Resolves the matching variant of a discriminated union from the value's tag.
165
149
  * Returns the matching schema or null if no match is found.
166
150
  */
167
- function resolveTaggedUnionSchema(source, schema) {
151
+ function resolveDiscriminatedUnionVariant(source, schema) {
168
152
  var schemaKey = schema.key;
169
- if (typeof schemaKey !== "string") {
170
- return null;
171
- }
172
153
  if (!source || slicedToArray._typeof(source) !== "object" || Array.isArray(source)) {
173
154
  return null;
174
155
  }
175
156
  var key = source[schemaKey];
176
- if (!key || typeof key !== "string") {
157
+ // The `typeof` check is the whole test: a falsy guard here would drop a
158
+ // variant tagged `s.literal("")`, whose strings would then never be encoded.
159
+ if (typeof key !== "string") {
177
160
  return null;
178
161
  }
179
162
  var matchingSchema = schema.items.find(function (s) {
@@ -182,31 +165,13 @@ function resolveTaggedUnionSchema(source, schema) {
182
165
  if (isLiteralSchema(keySchema)) {
183
166
  return keySchema.value === key;
184
167
  } else {
185
- console.warn("Expected literal schema at key in union, but found: ", keySchema, {
168
+ console.warn("Expected literal schema at key in discriminated union, but found: ", keySchema, {
186
169
  key: key,
187
170
  schema: s
188
171
  });
189
172
  }
190
173
  } else {
191
- console.warn("Expected union containing object schema, but found: ", s);
192
- }
193
- return false;
194
- });
195
- return matchingSchema || null;
196
- }
197
-
198
- /**
199
- * Resolves the matching sub-schema for a literal union (string-based).
200
- * Returns the matching schema or null if no match is found.
201
- */
202
- function resolveLiteralUnionSchema(source, schema) {
203
- var _ref;
204
- if (typeof schema.key === "string") {
205
- return null; // Not a literal union
206
- }
207
- var matchingSchema = (_ref = [schema.key]).concat.apply(_ref, _toConsumableArray(schema.items)).find(function (s) {
208
- if (isLiteralSchema(s)) {
209
- return s.value === source;
174
+ console.warn("Expected discriminated union containing object schema, but found: ", s);
210
175
  }
211
176
  return false;
212
177
  });
@@ -264,10 +229,10 @@ function handleRichTextSchema(sourceOrSelector, recOpts, rec) {
264
229
  // the schema. Passing the richtext schema down (as every other key does)
265
230
  // would leave it looking like a plain object, and it would lose its `url`.
266
231
  var imgSchema = sourceOrSelector.tag === "img" ? inlineImageSchemaOf(recOpts.schema) : undefined;
267
- var richtextSelector = Object.fromEntries(Object.entries(sourceOrSelector).map(function (_ref2) {
268
- var _ref3 = slicedToArray._slicedToArray(_ref2, 2),
269
- key = _ref3[0],
270
- value = _ref3[1];
232
+ var richtextSelector = Object.fromEntries(Object.entries(sourceOrSelector).map(function (_ref) {
233
+ var _ref2 = slicedToArray._slicedToArray(_ref, 2),
234
+ key = _ref2[0],
235
+ value = _ref2[1];
271
236
  return [key, key === "tag" || key === "styles" ? value : rec(value, {
272
237
  path: recOpts.path,
273
238
  schema: key === "src" && imgSchema ? imgSchema : recOpts.schema
@@ -300,25 +265,26 @@ function stegaEncode(input, opts) {
300
265
  if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isCodeSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
301
266
  return sourceOrSelector;
302
267
  }
303
- if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isUnionSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
304
- // Handle tagged union
305
- var taggedSchema = resolveTaggedUnionSchema(sourceOrSelector, recOpts.schema);
306
- if (taggedSchema) {
268
+ // A locale ends up in `<html lang>`, in `hreflang`, and in `Intl`
269
+ // constructors. None of those survive invisible characters: the attribute
270
+ // carries them into the markup, and `Intl` throws on a tag it cannot parse.
271
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isLocaleSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
272
+ return sourceOrSelector;
273
+ }
274
+ // An enum value is one of a fixed set of strings, and consumer code
275
+ // compares against those strings. Weaving stega into it would break every
276
+ // such comparison, so it is handed back verbatim — as a literal is.
277
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isEnumSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
278
+ return sourceOrSelector;
279
+ }
280
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isDiscriminatedUnionSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
281
+ var variantSchema = resolveDiscriminatedUnionVariant(sourceOrSelector, recOpts.schema);
282
+ if (variantSchema) {
307
283
  return rec(sourceOrSelector, {
308
284
  path: recOpts.path,
309
- schema: taggedSchema
285
+ schema: variantSchema
310
286
  });
311
287
  }
312
- // Handle literal union
313
- if (typeof sourceOrSelector === "string") {
314
- var literalSchema = resolveLiteralUnionSchema(sourceOrSelector, recOpts.schema);
315
- if (literalSchema) {
316
- return rec(sourceOrSelector, {
317
- path: recOpts.path,
318
- schema: literalSchema
319
- });
320
- }
321
- }
322
288
  // No match found, return as is
323
289
  return sourceOrSelector;
324
290
  }
@@ -413,6 +379,9 @@ function isDateTimeSchema(schema) {
413
379
  function isColorSchema(schema) {
414
380
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "color";
415
381
  }
382
+ function isLocaleSchema(schema) {
383
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "locale";
384
+ }
416
385
  function isCodeSchema(schema) {
417
386
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "code";
418
387
  }
@@ -420,8 +389,11 @@ function unknownSchema(schema) {
420
389
  console.debug("Found unknown schema", schema);
421
390
  return schema;
422
391
  }
423
- function isUnionSchema(schema) {
424
- return (schema === null || schema === void 0 ? void 0 : schema.type) === "union";
392
+ function isDiscriminatedUnionSchema(schema) {
393
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "discriminated-union";
394
+ }
395
+ function isEnumSchema(schema) {
396
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "enum";
425
397
  }
426
398
  function isKeyOfSchema(schema) {
427
399
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "keyOf";
@@ -450,7 +422,7 @@ function collectReferencedModulesFromSchema(schema, acc) {
450
422
  }
451
423
  } else if (schema.type === "array" || schema.type === "record") {
452
424
  collectReferencedModulesFromSchema(schema.item, acc);
453
- } else if (schema.type === "union") {
425
+ } else if (schema.type === "discriminated-union") {
454
426
  var _iterator = _createForOfIteratorHelper(schema.items),
455
427
  _step;
456
428
  try {
@@ -575,7 +547,6 @@ function raw(val) {
575
547
 
576
548
  exports._createForOfIteratorHelper = _createForOfIteratorHelper;
577
549
  exports._objectSpread2 = _objectSpread2;
578
- exports._toConsumableArray = _toConsumableArray;
579
550
  exports.attrs = attrs;
580
551
  exports.getModuleIds = getModuleIds;
581
552
  exports.raw = raw;
@@ -1,4 +1,4 @@
1
- import { b as _unsupportedIterableToArray, a as _typeof, c as _arrayLikeToArray, _ as _slicedToArray } from './slicedToArray-0c0a3b4a.esm.js';
1
+ import { b as _unsupportedIterableToArray, a as _typeof, _ as _slicedToArray } from './slicedToArray-9cce0d9f.browser.esm.js';
2
2
  import { Internal } from '@valbuild/core';
3
3
  import { vercelStegaDecodeAll, vercelStegaSplit, vercelStegaCombine } from '@vercel/stega';
4
4
 
@@ -122,22 +122,6 @@ function _objectSpread2(e) {
122
122
  return e;
123
123
  }
124
124
 
125
- function _arrayWithoutHoles(r) {
126
- if (Array.isArray(r)) return _arrayLikeToArray(r);
127
- }
128
-
129
- function _iterableToArray(r) {
130
- if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
131
- }
132
-
133
- function _nonIterableSpread() {
134
- throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
135
- }
136
-
137
- function _toConsumableArray(r) {
138
- return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
139
- }
140
-
141
125
  /**
142
126
  * ValEncodedString is a string that is encoded using steganography.
143
127
  *
@@ -159,19 +143,18 @@ function _toConsumableArray(r) {
159
143
  **/
160
144
 
161
145
  /**
162
- * Resolves the matching sub-schema for a tagged union based on the discriminator key.
146
+ * Resolves the matching variant of a discriminated union from the value's tag.
163
147
  * Returns the matching schema or null if no match is found.
164
148
  */
165
- function resolveTaggedUnionSchema(source, schema) {
149
+ function resolveDiscriminatedUnionVariant(source, schema) {
166
150
  var schemaKey = schema.key;
167
- if (typeof schemaKey !== "string") {
168
- return null;
169
- }
170
151
  if (!source || _typeof(source) !== "object" || Array.isArray(source)) {
171
152
  return null;
172
153
  }
173
154
  var key = source[schemaKey];
174
- if (!key || typeof key !== "string") {
155
+ // The `typeof` check is the whole test: a falsy guard here would drop a
156
+ // variant tagged `s.literal("")`, whose strings would then never be encoded.
157
+ if (typeof key !== "string") {
175
158
  return null;
176
159
  }
177
160
  var matchingSchema = schema.items.find(function (s) {
@@ -180,31 +163,13 @@ function resolveTaggedUnionSchema(source, schema) {
180
163
  if (isLiteralSchema(keySchema)) {
181
164
  return keySchema.value === key;
182
165
  } else {
183
- console.warn("Expected literal schema at key in union, but found: ", keySchema, {
166
+ console.warn("Expected literal schema at key in discriminated union, but found: ", keySchema, {
184
167
  key: key,
185
168
  schema: s
186
169
  });
187
170
  }
188
171
  } else {
189
- console.warn("Expected union containing object schema, but found: ", s);
190
- }
191
- return false;
192
- });
193
- return matchingSchema || null;
194
- }
195
-
196
- /**
197
- * Resolves the matching sub-schema for a literal union (string-based).
198
- * Returns the matching schema or null if no match is found.
199
- */
200
- function resolveLiteralUnionSchema(source, schema) {
201
- var _ref;
202
- if (typeof schema.key === "string") {
203
- return null; // Not a literal union
204
- }
205
- var matchingSchema = (_ref = [schema.key]).concat.apply(_ref, _toConsumableArray(schema.items)).find(function (s) {
206
- if (isLiteralSchema(s)) {
207
- return s.value === source;
172
+ console.warn("Expected discriminated union containing object schema, but found: ", s);
208
173
  }
209
174
  return false;
210
175
  });
@@ -262,10 +227,10 @@ function handleRichTextSchema(sourceOrSelector, recOpts, rec) {
262
227
  // the schema. Passing the richtext schema down (as every other key does)
263
228
  // would leave it looking like a plain object, and it would lose its `url`.
264
229
  var imgSchema = sourceOrSelector.tag === "img" ? inlineImageSchemaOf(recOpts.schema) : undefined;
265
- var richtextSelector = Object.fromEntries(Object.entries(sourceOrSelector).map(function (_ref2) {
266
- var _ref3 = _slicedToArray(_ref2, 2),
267
- key = _ref3[0],
268
- value = _ref3[1];
230
+ var richtextSelector = Object.fromEntries(Object.entries(sourceOrSelector).map(function (_ref) {
231
+ var _ref2 = _slicedToArray(_ref, 2),
232
+ key = _ref2[0],
233
+ value = _ref2[1];
269
234
  return [key, key === "tag" || key === "styles" ? value : rec(value, {
270
235
  path: recOpts.path,
271
236
  schema: key === "src" && imgSchema ? imgSchema : recOpts.schema
@@ -298,25 +263,26 @@ function stegaEncode(input, opts) {
298
263
  if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isCodeSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
299
264
  return sourceOrSelector;
300
265
  }
301
- if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isUnionSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
302
- // Handle tagged union
303
- var taggedSchema = resolveTaggedUnionSchema(sourceOrSelector, recOpts.schema);
304
- if (taggedSchema) {
266
+ // A locale ends up in `<html lang>`, in `hreflang`, and in `Intl`
267
+ // constructors. None of those survive invisible characters: the attribute
268
+ // carries them into the markup, and `Intl` throws on a tag it cannot parse.
269
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isLocaleSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
270
+ return sourceOrSelector;
271
+ }
272
+ // An enum value is one of a fixed set of strings, and consumer code
273
+ // compares against those strings. Weaving stega into it would break every
274
+ // such comparison, so it is handed back verbatim — as a literal is.
275
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isEnumSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
276
+ return sourceOrSelector;
277
+ }
278
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isDiscriminatedUnionSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
279
+ var variantSchema = resolveDiscriminatedUnionVariant(sourceOrSelector, recOpts.schema);
280
+ if (variantSchema) {
305
281
  return rec(sourceOrSelector, {
306
282
  path: recOpts.path,
307
- schema: taggedSchema
283
+ schema: variantSchema
308
284
  });
309
285
  }
310
- // Handle literal union
311
- if (typeof sourceOrSelector === "string") {
312
- var literalSchema = resolveLiteralUnionSchema(sourceOrSelector, recOpts.schema);
313
- if (literalSchema) {
314
- return rec(sourceOrSelector, {
315
- path: recOpts.path,
316
- schema: literalSchema
317
- });
318
- }
319
- }
320
286
  // No match found, return as is
321
287
  return sourceOrSelector;
322
288
  }
@@ -411,6 +377,9 @@ function isDateTimeSchema(schema) {
411
377
  function isColorSchema(schema) {
412
378
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "color";
413
379
  }
380
+ function isLocaleSchema(schema) {
381
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "locale";
382
+ }
414
383
  function isCodeSchema(schema) {
415
384
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "code";
416
385
  }
@@ -418,8 +387,11 @@ function unknownSchema(schema) {
418
387
  console.debug("Found unknown schema", schema);
419
388
  return schema;
420
389
  }
421
- function isUnionSchema(schema) {
422
- return (schema === null || schema === void 0 ? void 0 : schema.type) === "union";
390
+ function isDiscriminatedUnionSchema(schema) {
391
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "discriminated-union";
392
+ }
393
+ function isEnumSchema(schema) {
394
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "enum";
423
395
  }
424
396
  function isKeyOfSchema(schema) {
425
397
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "keyOf";
@@ -448,7 +420,7 @@ function collectReferencedModulesFromSchema(schema, acc) {
448
420
  }
449
421
  } else if (schema.type === "array" || schema.type === "record") {
450
422
  collectReferencedModulesFromSchema(schema.item, acc);
451
- } else if (schema.type === "union") {
423
+ } else if (schema.type === "discriminated-union") {
452
424
  var _iterator = _createForOfIteratorHelper(schema.items),
453
425
  _step;
454
426
  try {
@@ -571,4 +543,4 @@ function raw(val) {
571
543
  return val;
572
544
  }
573
545
 
574
- export { _createForOfIteratorHelper as _, stegaEncode as a, stegaClean as b, attrs as c, _objectSpread2 as d, _toConsumableArray as e, getModuleIds as g, raw as r, stegaDecodeStrings as s };
546
+ export { _createForOfIteratorHelper as _, stegaEncode as a, stegaClean as b, attrs as c, _objectSpread2 as d, getModuleIds as g, raw as r, stegaDecodeStrings as s };
@@ -1,4 +1,4 @@
1
- import { b as _unsupportedIterableToArray, a as _typeof, c as _arrayLikeToArray, _ as _slicedToArray } from './slicedToArray-7d0170b6.worker.esm.js';
1
+ import { b as _unsupportedIterableToArray, a as _typeof, _ as _slicedToArray } from './slicedToArray-0c0a3b4a.esm.js';
2
2
  import { Internal } from '@valbuild/core';
3
3
  import { vercelStegaDecodeAll, vercelStegaSplit, vercelStegaCombine } from '@vercel/stega';
4
4
 
@@ -122,22 +122,6 @@ function _objectSpread2(e) {
122
122
  return e;
123
123
  }
124
124
 
125
- function _arrayWithoutHoles(r) {
126
- if (Array.isArray(r)) return _arrayLikeToArray(r);
127
- }
128
-
129
- function _iterableToArray(r) {
130
- if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
131
- }
132
-
133
- function _nonIterableSpread() {
134
- throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
135
- }
136
-
137
- function _toConsumableArray(r) {
138
- return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
139
- }
140
-
141
125
  /**
142
126
  * ValEncodedString is a string that is encoded using steganography.
143
127
  *
@@ -159,19 +143,18 @@ function _toConsumableArray(r) {
159
143
  **/
160
144
 
161
145
  /**
162
- * Resolves the matching sub-schema for a tagged union based on the discriminator key.
146
+ * Resolves the matching variant of a discriminated union from the value's tag.
163
147
  * Returns the matching schema or null if no match is found.
164
148
  */
165
- function resolveTaggedUnionSchema(source, schema) {
149
+ function resolveDiscriminatedUnionVariant(source, schema) {
166
150
  var schemaKey = schema.key;
167
- if (typeof schemaKey !== "string") {
168
- return null;
169
- }
170
151
  if (!source || _typeof(source) !== "object" || Array.isArray(source)) {
171
152
  return null;
172
153
  }
173
154
  var key = source[schemaKey];
174
- if (!key || typeof key !== "string") {
155
+ // The `typeof` check is the whole test: a falsy guard here would drop a
156
+ // variant tagged `s.literal("")`, whose strings would then never be encoded.
157
+ if (typeof key !== "string") {
175
158
  return null;
176
159
  }
177
160
  var matchingSchema = schema.items.find(function (s) {
@@ -180,31 +163,13 @@ function resolveTaggedUnionSchema(source, schema) {
180
163
  if (isLiteralSchema(keySchema)) {
181
164
  return keySchema.value === key;
182
165
  } else {
183
- console.warn("Expected literal schema at key in union, but found: ", keySchema, {
166
+ console.warn("Expected literal schema at key in discriminated union, but found: ", keySchema, {
184
167
  key: key,
185
168
  schema: s
186
169
  });
187
170
  }
188
171
  } else {
189
- console.warn("Expected union containing object schema, but found: ", s);
190
- }
191
- return false;
192
- });
193
- return matchingSchema || null;
194
- }
195
-
196
- /**
197
- * Resolves the matching sub-schema for a literal union (string-based).
198
- * Returns the matching schema or null if no match is found.
199
- */
200
- function resolveLiteralUnionSchema(source, schema) {
201
- var _ref;
202
- if (typeof schema.key === "string") {
203
- return null; // Not a literal union
204
- }
205
- var matchingSchema = (_ref = [schema.key]).concat.apply(_ref, _toConsumableArray(schema.items)).find(function (s) {
206
- if (isLiteralSchema(s)) {
207
- return s.value === source;
172
+ console.warn("Expected discriminated union containing object schema, but found: ", s);
208
173
  }
209
174
  return false;
210
175
  });
@@ -262,10 +227,10 @@ function handleRichTextSchema(sourceOrSelector, recOpts, rec) {
262
227
  // the schema. Passing the richtext schema down (as every other key does)
263
228
  // would leave it looking like a plain object, and it would lose its `url`.
264
229
  var imgSchema = sourceOrSelector.tag === "img" ? inlineImageSchemaOf(recOpts.schema) : undefined;
265
- var richtextSelector = Object.fromEntries(Object.entries(sourceOrSelector).map(function (_ref2) {
266
- var _ref3 = _slicedToArray(_ref2, 2),
267
- key = _ref3[0],
268
- value = _ref3[1];
230
+ var richtextSelector = Object.fromEntries(Object.entries(sourceOrSelector).map(function (_ref) {
231
+ var _ref2 = _slicedToArray(_ref, 2),
232
+ key = _ref2[0],
233
+ value = _ref2[1];
269
234
  return [key, key === "tag" || key === "styles" ? value : rec(value, {
270
235
  path: recOpts.path,
271
236
  schema: key === "src" && imgSchema ? imgSchema : recOpts.schema
@@ -298,25 +263,26 @@ function stegaEncode(input, opts) {
298
263
  if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isCodeSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
299
264
  return sourceOrSelector;
300
265
  }
301
- if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isUnionSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
302
- // Handle tagged union
303
- var taggedSchema = resolveTaggedUnionSchema(sourceOrSelector, recOpts.schema);
304
- if (taggedSchema) {
266
+ // A locale ends up in `<html lang>`, in `hreflang`, and in `Intl`
267
+ // constructors. None of those survive invisible characters: the attribute
268
+ // carries them into the markup, and `Intl` throws on a tag it cannot parse.
269
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isLocaleSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
270
+ return sourceOrSelector;
271
+ }
272
+ // An enum value is one of a fixed set of strings, and consumer code
273
+ // compares against those strings. Weaving stega into it would break every
274
+ // such comparison, so it is handed back verbatim — as a literal is.
275
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isEnumSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
276
+ return sourceOrSelector;
277
+ }
278
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isDiscriminatedUnionSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
279
+ var variantSchema = resolveDiscriminatedUnionVariant(sourceOrSelector, recOpts.schema);
280
+ if (variantSchema) {
305
281
  return rec(sourceOrSelector, {
306
282
  path: recOpts.path,
307
- schema: taggedSchema
283
+ schema: variantSchema
308
284
  });
309
285
  }
310
- // Handle literal union
311
- if (typeof sourceOrSelector === "string") {
312
- var literalSchema = resolveLiteralUnionSchema(sourceOrSelector, recOpts.schema);
313
- if (literalSchema) {
314
- return rec(sourceOrSelector, {
315
- path: recOpts.path,
316
- schema: literalSchema
317
- });
318
- }
319
- }
320
286
  // No match found, return as is
321
287
  return sourceOrSelector;
322
288
  }
@@ -411,6 +377,9 @@ function isDateTimeSchema(schema) {
411
377
  function isColorSchema(schema) {
412
378
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "color";
413
379
  }
380
+ function isLocaleSchema(schema) {
381
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "locale";
382
+ }
414
383
  function isCodeSchema(schema) {
415
384
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "code";
416
385
  }
@@ -418,8 +387,11 @@ function unknownSchema(schema) {
418
387
  console.debug("Found unknown schema", schema);
419
388
  return schema;
420
389
  }
421
- function isUnionSchema(schema) {
422
- return (schema === null || schema === void 0 ? void 0 : schema.type) === "union";
390
+ function isDiscriminatedUnionSchema(schema) {
391
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "discriminated-union";
392
+ }
393
+ function isEnumSchema(schema) {
394
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "enum";
423
395
  }
424
396
  function isKeyOfSchema(schema) {
425
397
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "keyOf";
@@ -448,7 +420,7 @@ function collectReferencedModulesFromSchema(schema, acc) {
448
420
  }
449
421
  } else if (schema.type === "array" || schema.type === "record") {
450
422
  collectReferencedModulesFromSchema(schema.item, acc);
451
- } else if (schema.type === "union") {
423
+ } else if (schema.type === "discriminated-union") {
452
424
  var _iterator = _createForOfIteratorHelper(schema.items),
453
425
  _step;
454
426
  try {
@@ -571,4 +543,4 @@ function raw(val) {
571
543
  return val;
572
544
  }
573
545
 
574
- export { _createForOfIteratorHelper as _, stegaEncode as a, stegaClean as b, attrs as c, _objectSpread2 as d, _toConsumableArray as e, getModuleIds as g, raw as r, stegaDecodeStrings as s };
546
+ export { _createForOfIteratorHelper as _, stegaEncode as a, stegaClean as b, attrs as c, _objectSpread2 as d, getModuleIds as g, raw as r, stegaDecodeStrings as s };
@@ -1,4 +1,4 @@
1
- import { b as _unsupportedIterableToArray, a as _typeof, c as _arrayLikeToArray, _ as _slicedToArray } from './slicedToArray-9cce0d9f.browser.esm.js';
1
+ import { b as _unsupportedIterableToArray, a as _typeof, _ as _slicedToArray } from './slicedToArray-7d0170b6.worker.esm.js';
2
2
  import { Internal } from '@valbuild/core';
3
3
  import { vercelStegaDecodeAll, vercelStegaSplit, vercelStegaCombine } from '@vercel/stega';
4
4
 
@@ -122,22 +122,6 @@ function _objectSpread2(e) {
122
122
  return e;
123
123
  }
124
124
 
125
- function _arrayWithoutHoles(r) {
126
- if (Array.isArray(r)) return _arrayLikeToArray(r);
127
- }
128
-
129
- function _iterableToArray(r) {
130
- if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
131
- }
132
-
133
- function _nonIterableSpread() {
134
- throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
135
- }
136
-
137
- function _toConsumableArray(r) {
138
- return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
139
- }
140
-
141
125
  /**
142
126
  * ValEncodedString is a string that is encoded using steganography.
143
127
  *
@@ -159,19 +143,18 @@ function _toConsumableArray(r) {
159
143
  **/
160
144
 
161
145
  /**
162
- * Resolves the matching sub-schema for a tagged union based on the discriminator key.
146
+ * Resolves the matching variant of a discriminated union from the value's tag.
163
147
  * Returns the matching schema or null if no match is found.
164
148
  */
165
- function resolveTaggedUnionSchema(source, schema) {
149
+ function resolveDiscriminatedUnionVariant(source, schema) {
166
150
  var schemaKey = schema.key;
167
- if (typeof schemaKey !== "string") {
168
- return null;
169
- }
170
151
  if (!source || _typeof(source) !== "object" || Array.isArray(source)) {
171
152
  return null;
172
153
  }
173
154
  var key = source[schemaKey];
174
- if (!key || typeof key !== "string") {
155
+ // The `typeof` check is the whole test: a falsy guard here would drop a
156
+ // variant tagged `s.literal("")`, whose strings would then never be encoded.
157
+ if (typeof key !== "string") {
175
158
  return null;
176
159
  }
177
160
  var matchingSchema = schema.items.find(function (s) {
@@ -180,31 +163,13 @@ function resolveTaggedUnionSchema(source, schema) {
180
163
  if (isLiteralSchema(keySchema)) {
181
164
  return keySchema.value === key;
182
165
  } else {
183
- console.warn("Expected literal schema at key in union, but found: ", keySchema, {
166
+ console.warn("Expected literal schema at key in discriminated union, but found: ", keySchema, {
184
167
  key: key,
185
168
  schema: s
186
169
  });
187
170
  }
188
171
  } else {
189
- console.warn("Expected union containing object schema, but found: ", s);
190
- }
191
- return false;
192
- });
193
- return matchingSchema || null;
194
- }
195
-
196
- /**
197
- * Resolves the matching sub-schema for a literal union (string-based).
198
- * Returns the matching schema or null if no match is found.
199
- */
200
- function resolveLiteralUnionSchema(source, schema) {
201
- var _ref;
202
- if (typeof schema.key === "string") {
203
- return null; // Not a literal union
204
- }
205
- var matchingSchema = (_ref = [schema.key]).concat.apply(_ref, _toConsumableArray(schema.items)).find(function (s) {
206
- if (isLiteralSchema(s)) {
207
- return s.value === source;
172
+ console.warn("Expected discriminated union containing object schema, but found: ", s);
208
173
  }
209
174
  return false;
210
175
  });
@@ -262,10 +227,10 @@ function handleRichTextSchema(sourceOrSelector, recOpts, rec) {
262
227
  // the schema. Passing the richtext schema down (as every other key does)
263
228
  // would leave it looking like a plain object, and it would lose its `url`.
264
229
  var imgSchema = sourceOrSelector.tag === "img" ? inlineImageSchemaOf(recOpts.schema) : undefined;
265
- var richtextSelector = Object.fromEntries(Object.entries(sourceOrSelector).map(function (_ref2) {
266
- var _ref3 = _slicedToArray(_ref2, 2),
267
- key = _ref3[0],
268
- value = _ref3[1];
230
+ var richtextSelector = Object.fromEntries(Object.entries(sourceOrSelector).map(function (_ref) {
231
+ var _ref2 = _slicedToArray(_ref, 2),
232
+ key = _ref2[0],
233
+ value = _ref2[1];
269
234
  return [key, key === "tag" || key === "styles" ? value : rec(value, {
270
235
  path: recOpts.path,
271
236
  schema: key === "src" && imgSchema ? imgSchema : recOpts.schema
@@ -298,25 +263,26 @@ function stegaEncode(input, opts) {
298
263
  if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isCodeSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
299
264
  return sourceOrSelector;
300
265
  }
301
- if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isUnionSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
302
- // Handle tagged union
303
- var taggedSchema = resolveTaggedUnionSchema(sourceOrSelector, recOpts.schema);
304
- if (taggedSchema) {
266
+ // A locale ends up in `<html lang>`, in `hreflang`, and in `Intl`
267
+ // constructors. None of those survive invisible characters: the attribute
268
+ // carries them into the markup, and `Intl` throws on a tag it cannot parse.
269
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isLocaleSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
270
+ return sourceOrSelector;
271
+ }
272
+ // An enum value is one of a fixed set of strings, and consumer code
273
+ // compares against those strings. Weaving stega into it would break every
274
+ // such comparison, so it is handed back verbatim — as a literal is.
275
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isEnumSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
276
+ return sourceOrSelector;
277
+ }
278
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isDiscriminatedUnionSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
279
+ var variantSchema = resolveDiscriminatedUnionVariant(sourceOrSelector, recOpts.schema);
280
+ if (variantSchema) {
305
281
  return rec(sourceOrSelector, {
306
282
  path: recOpts.path,
307
- schema: taggedSchema
283
+ schema: variantSchema
308
284
  });
309
285
  }
310
- // Handle literal union
311
- if (typeof sourceOrSelector === "string") {
312
- var literalSchema = resolveLiteralUnionSchema(sourceOrSelector, recOpts.schema);
313
- if (literalSchema) {
314
- return rec(sourceOrSelector, {
315
- path: recOpts.path,
316
- schema: literalSchema
317
- });
318
- }
319
- }
320
286
  // No match found, return as is
321
287
  return sourceOrSelector;
322
288
  }
@@ -411,6 +377,9 @@ function isDateTimeSchema(schema) {
411
377
  function isColorSchema(schema) {
412
378
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "color";
413
379
  }
380
+ function isLocaleSchema(schema) {
381
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "locale";
382
+ }
414
383
  function isCodeSchema(schema) {
415
384
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "code";
416
385
  }
@@ -418,8 +387,11 @@ function unknownSchema(schema) {
418
387
  console.debug("Found unknown schema", schema);
419
388
  return schema;
420
389
  }
421
- function isUnionSchema(schema) {
422
- return (schema === null || schema === void 0 ? void 0 : schema.type) === "union";
390
+ function isDiscriminatedUnionSchema(schema) {
391
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "discriminated-union";
392
+ }
393
+ function isEnumSchema(schema) {
394
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "enum";
423
395
  }
424
396
  function isKeyOfSchema(schema) {
425
397
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "keyOf";
@@ -448,7 +420,7 @@ function collectReferencedModulesFromSchema(schema, acc) {
448
420
  }
449
421
  } else if (schema.type === "array" || schema.type === "record") {
450
422
  collectReferencedModulesFromSchema(schema.item, acc);
451
- } else if (schema.type === "union") {
423
+ } else if (schema.type === "discriminated-union") {
452
424
  var _iterator = _createForOfIteratorHelper(schema.items),
453
425
  _step;
454
426
  try {
@@ -571,4 +543,4 @@ function raw(val) {
571
543
  return val;
572
544
  }
573
545
 
574
- export { _createForOfIteratorHelper as _, stegaEncode as a, stegaClean as b, attrs as c, _objectSpread2 as d, _toConsumableArray as e, getModuleIds as g, raw as r, stegaDecodeStrings as s };
546
+ export { _createForOfIteratorHelper as _, stegaEncode as a, stegaClean as b, attrs as c, _objectSpread2 as d, getModuleIds as g, raw as r, stegaDecodeStrings as s };
@@ -124,22 +124,6 @@ function _objectSpread2(e) {
124
124
  return e;
125
125
  }
126
126
 
127
- function _arrayWithoutHoles(r) {
128
- if (Array.isArray(r)) return slicedToArray._arrayLikeToArray(r);
129
- }
130
-
131
- function _iterableToArray(r) {
132
- if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
133
- }
134
-
135
- function _nonIterableSpread() {
136
- throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
137
- }
138
-
139
- function _toConsumableArray(r) {
140
- return _arrayWithoutHoles(r) || _iterableToArray(r) || slicedToArray._unsupportedIterableToArray(r) || _nonIterableSpread();
141
- }
142
-
143
127
  /**
144
128
  * ValEncodedString is a string that is encoded using steganography.
145
129
  *
@@ -161,19 +145,18 @@ function _toConsumableArray(r) {
161
145
  **/
162
146
 
163
147
  /**
164
- * Resolves the matching sub-schema for a tagged union based on the discriminator key.
148
+ * Resolves the matching variant of a discriminated union from the value's tag.
165
149
  * Returns the matching schema or null if no match is found.
166
150
  */
167
- function resolveTaggedUnionSchema(source, schema) {
151
+ function resolveDiscriminatedUnionVariant(source, schema) {
168
152
  var schemaKey = schema.key;
169
- if (typeof schemaKey !== "string") {
170
- return null;
171
- }
172
153
  if (!source || slicedToArray._typeof(source) !== "object" || Array.isArray(source)) {
173
154
  return null;
174
155
  }
175
156
  var key = source[schemaKey];
176
- if (!key || typeof key !== "string") {
157
+ // The `typeof` check is the whole test: a falsy guard here would drop a
158
+ // variant tagged `s.literal("")`, whose strings would then never be encoded.
159
+ if (typeof key !== "string") {
177
160
  return null;
178
161
  }
179
162
  var matchingSchema = schema.items.find(function (s) {
@@ -182,31 +165,13 @@ function resolveTaggedUnionSchema(source, schema) {
182
165
  if (isLiteralSchema(keySchema)) {
183
166
  return keySchema.value === key;
184
167
  } else {
185
- console.warn("Expected literal schema at key in union, but found: ", keySchema, {
168
+ console.warn("Expected literal schema at key in discriminated union, but found: ", keySchema, {
186
169
  key: key,
187
170
  schema: s
188
171
  });
189
172
  }
190
173
  } else {
191
- console.warn("Expected union containing object schema, but found: ", s);
192
- }
193
- return false;
194
- });
195
- return matchingSchema || null;
196
- }
197
-
198
- /**
199
- * Resolves the matching sub-schema for a literal union (string-based).
200
- * Returns the matching schema or null if no match is found.
201
- */
202
- function resolveLiteralUnionSchema(source, schema) {
203
- var _ref;
204
- if (typeof schema.key === "string") {
205
- return null; // Not a literal union
206
- }
207
- var matchingSchema = (_ref = [schema.key]).concat.apply(_ref, _toConsumableArray(schema.items)).find(function (s) {
208
- if (isLiteralSchema(s)) {
209
- return s.value === source;
174
+ console.warn("Expected discriminated union containing object schema, but found: ", s);
210
175
  }
211
176
  return false;
212
177
  });
@@ -264,10 +229,10 @@ function handleRichTextSchema(sourceOrSelector, recOpts, rec) {
264
229
  // the schema. Passing the richtext schema down (as every other key does)
265
230
  // would leave it looking like a plain object, and it would lose its `url`.
266
231
  var imgSchema = sourceOrSelector.tag === "img" ? inlineImageSchemaOf(recOpts.schema) : undefined;
267
- var richtextSelector = Object.fromEntries(Object.entries(sourceOrSelector).map(function (_ref2) {
268
- var _ref3 = slicedToArray._slicedToArray(_ref2, 2),
269
- key = _ref3[0],
270
- value = _ref3[1];
232
+ var richtextSelector = Object.fromEntries(Object.entries(sourceOrSelector).map(function (_ref) {
233
+ var _ref2 = slicedToArray._slicedToArray(_ref, 2),
234
+ key = _ref2[0],
235
+ value = _ref2[1];
271
236
  return [key, key === "tag" || key === "styles" ? value : rec(value, {
272
237
  path: recOpts.path,
273
238
  schema: key === "src" && imgSchema ? imgSchema : recOpts.schema
@@ -300,25 +265,26 @@ function stegaEncode(input, opts) {
300
265
  if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isCodeSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
301
266
  return sourceOrSelector;
302
267
  }
303
- if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isUnionSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
304
- // Handle tagged union
305
- var taggedSchema = resolveTaggedUnionSchema(sourceOrSelector, recOpts.schema);
306
- if (taggedSchema) {
268
+ // A locale ends up in `<html lang>`, in `hreflang`, and in `Intl`
269
+ // constructors. None of those survive invisible characters: the attribute
270
+ // carries them into the markup, and `Intl` throws on a tag it cannot parse.
271
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isLocaleSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
272
+ return sourceOrSelector;
273
+ }
274
+ // An enum value is one of a fixed set of strings, and consumer code
275
+ // compares against those strings. Weaving stega into it would break every
276
+ // such comparison, so it is handed back verbatim — as a literal is.
277
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isEnumSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
278
+ return sourceOrSelector;
279
+ }
280
+ if (recOpts !== null && recOpts !== void 0 && recOpts.schema && isDiscriminatedUnionSchema(recOpts === null || recOpts === void 0 ? void 0 : recOpts.schema)) {
281
+ var variantSchema = resolveDiscriminatedUnionVariant(sourceOrSelector, recOpts.schema);
282
+ if (variantSchema) {
307
283
  return rec(sourceOrSelector, {
308
284
  path: recOpts.path,
309
- schema: taggedSchema
285
+ schema: variantSchema
310
286
  });
311
287
  }
312
- // Handle literal union
313
- if (typeof sourceOrSelector === "string") {
314
- var literalSchema = resolveLiteralUnionSchema(sourceOrSelector, recOpts.schema);
315
- if (literalSchema) {
316
- return rec(sourceOrSelector, {
317
- path: recOpts.path,
318
- schema: literalSchema
319
- });
320
- }
321
- }
322
288
  // No match found, return as is
323
289
  return sourceOrSelector;
324
290
  }
@@ -413,6 +379,9 @@ function isDateTimeSchema(schema) {
413
379
  function isColorSchema(schema) {
414
380
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "color";
415
381
  }
382
+ function isLocaleSchema(schema) {
383
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "locale";
384
+ }
416
385
  function isCodeSchema(schema) {
417
386
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "code";
418
387
  }
@@ -420,8 +389,11 @@ function unknownSchema(schema) {
420
389
  console.debug("Found unknown schema", schema);
421
390
  return schema;
422
391
  }
423
- function isUnionSchema(schema) {
424
- return (schema === null || schema === void 0 ? void 0 : schema.type) === "union";
392
+ function isDiscriminatedUnionSchema(schema) {
393
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "discriminated-union";
394
+ }
395
+ function isEnumSchema(schema) {
396
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === "enum";
425
397
  }
426
398
  function isKeyOfSchema(schema) {
427
399
  return (schema === null || schema === void 0 ? void 0 : schema.type) === "keyOf";
@@ -450,7 +422,7 @@ function collectReferencedModulesFromSchema(schema, acc) {
450
422
  }
451
423
  } else if (schema.type === "array" || schema.type === "record") {
452
424
  collectReferencedModulesFromSchema(schema.item, acc);
453
- } else if (schema.type === "union") {
425
+ } else if (schema.type === "discriminated-union") {
454
426
  var _iterator = _createForOfIteratorHelper(schema.items),
455
427
  _step;
456
428
  try {
@@ -575,7 +547,6 @@ function raw(val) {
575
547
 
576
548
  exports._createForOfIteratorHelper = _createForOfIteratorHelper;
577
549
  exports._objectSpread2 = _objectSpread2;
578
- exports._toConsumableArray = _toConsumableArray;
579
550
  exports.attrs = attrs;
580
551
  exports.getModuleIds = getModuleIds;
581
552
  exports.raw = raw;
@@ -1,10 +1,26 @@
1
- import { d as _objectSpread2, r as raw, c as attrs, e as _toConsumableArray } from '../../dist/raw-76ccee5c.browser.esm.js';
1
+ import { c as _arrayLikeToArray, b as _unsupportedIterableToArray } from '../../dist/slicedToArray-9cce0d9f.browser.esm.js';
2
+ import { d as _objectSpread2, r as raw, c as attrs } from '../../dist/raw-57f19ada.browser.esm.js';
2
3
  import React from 'react';
3
4
  import { jsx } from 'react/jsx-runtime';
4
- import '../../dist/slicedToArray-9cce0d9f.browser.esm.js';
5
5
  import '@valbuild/core';
6
6
  import '@vercel/stega';
7
7
 
8
+ function _arrayWithoutHoles(r) {
9
+ if (Array.isArray(r)) return _arrayLikeToArray(r);
10
+ }
11
+
12
+ function _iterableToArray(r) {
13
+ if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
14
+ }
15
+
16
+ function _nonIterableSpread() {
17
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
18
+ }
19
+
20
+ function _toConsumableArray(r) {
21
+ return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
22
+ }
23
+
8
24
  function _objectWithoutPropertiesLoose(r, e) {
9
25
  if (null == r) return {};
10
26
  var t = {};
@@ -2,10 +2,10 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var raw = require('../../dist/raw-44cf5d7f.cjs.dev.js');
5
+ var slicedToArray = require('../../dist/slicedToArray-e9e8e991.cjs.dev.js');
6
+ var raw = require('../../dist/raw-512e7a0a.cjs.dev.js');
6
7
  var React = require('react');
7
8
  var ReactJSXRuntime = require('react/jsx-runtime');
8
- require('../../dist/slicedToArray-e9e8e991.cjs.dev.js');
9
9
  require('@valbuild/core');
10
10
  require('@vercel/stega');
11
11
 
@@ -13,6 +13,22 @@ function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e };
13
13
 
14
14
  var React__default = /*#__PURE__*/_interopDefault(React);
15
15
 
16
+ function _arrayWithoutHoles(r) {
17
+ if (Array.isArray(r)) return slicedToArray._arrayLikeToArray(r);
18
+ }
19
+
20
+ function _iterableToArray(r) {
21
+ if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
22
+ }
23
+
24
+ function _nonIterableSpread() {
25
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
26
+ }
27
+
28
+ function _toConsumableArray(r) {
29
+ return _arrayWithoutHoles(r) || _iterableToArray(r) || slicedToArray._unsupportedIterableToArray(r) || _nonIterableSpread();
30
+ }
31
+
16
32
  function _objectWithoutPropertiesLoose(r, e) {
17
33
  if (null == r) return {};
18
34
  var t = {};
@@ -136,7 +152,7 @@ function classNameOfTag(tag, style, theme) {
136
152
  var _tag;
137
153
  thisTagClassName = (_tag = theme[tag]) !== null && _tag !== void 0 ? _tag : null;
138
154
  }
139
- return [].concat(raw._toConsumableArray(thisTagClassName ? [thisTagClassName] : []), raw._toConsumableArray(style.map(function (style) {
155
+ return [].concat(_toConsumableArray(thisTagClassName ? [thisTagClassName] : []), _toConsumableArray(style.map(function (style) {
140
156
  if (theme &&
141
157
  // not need on type-level, but defensive on runtime:
142
158
  typeof style === "string") {
@@ -2,10 +2,10 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var raw = require('../../dist/raw-c75f7272.cjs.prod.js');
5
+ var slicedToArray = require('../../dist/slicedToArray-86004d59.cjs.prod.js');
6
+ var raw = require('../../dist/raw-fe78b046.cjs.prod.js');
6
7
  var React = require('react');
7
8
  var ReactJSXRuntime = require('react/jsx-runtime');
8
- require('../../dist/slicedToArray-86004d59.cjs.prod.js');
9
9
  require('@valbuild/core');
10
10
  require('@vercel/stega');
11
11
 
@@ -13,6 +13,22 @@ function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e };
13
13
 
14
14
  var React__default = /*#__PURE__*/_interopDefault(React);
15
15
 
16
+ function _arrayWithoutHoles(r) {
17
+ if (Array.isArray(r)) return slicedToArray._arrayLikeToArray(r);
18
+ }
19
+
20
+ function _iterableToArray(r) {
21
+ if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
22
+ }
23
+
24
+ function _nonIterableSpread() {
25
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
26
+ }
27
+
28
+ function _toConsumableArray(r) {
29
+ return _arrayWithoutHoles(r) || _iterableToArray(r) || slicedToArray._unsupportedIterableToArray(r) || _nonIterableSpread();
30
+ }
31
+
16
32
  function _objectWithoutPropertiesLoose(r, e) {
17
33
  if (null == r) return {};
18
34
  var t = {};
@@ -136,7 +152,7 @@ function classNameOfTag(tag, style, theme) {
136
152
  var _tag;
137
153
  thisTagClassName = (_tag = theme[tag]) !== null && _tag !== void 0 ? _tag : null;
138
154
  }
139
- return [].concat(raw._toConsumableArray(thisTagClassName ? [thisTagClassName] : []), raw._toConsumableArray(style.map(function (style) {
155
+ return [].concat(_toConsumableArray(thisTagClassName ? [thisTagClassName] : []), _toConsumableArray(style.map(function (style) {
140
156
  if (theme &&
141
157
  // not need on type-level, but defensive on runtime:
142
158
  typeof style === "string") {
@@ -1,10 +1,26 @@
1
- import { d as _objectSpread2, r as raw, c as attrs, e as _toConsumableArray } from '../../dist/raw-8453ef90.esm.js';
1
+ import { c as _arrayLikeToArray, b as _unsupportedIterableToArray } from '../../dist/slicedToArray-0c0a3b4a.esm.js';
2
+ import { d as _objectSpread2, r as raw, c as attrs } from '../../dist/raw-7ce61255.esm.js';
2
3
  import React from 'react';
3
4
  import { jsx } from 'react/jsx-runtime';
4
- import '../../dist/slicedToArray-0c0a3b4a.esm.js';
5
5
  import '@valbuild/core';
6
6
  import '@vercel/stega';
7
7
 
8
+ function _arrayWithoutHoles(r) {
9
+ if (Array.isArray(r)) return _arrayLikeToArray(r);
10
+ }
11
+
12
+ function _iterableToArray(r) {
13
+ if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
14
+ }
15
+
16
+ function _nonIterableSpread() {
17
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
18
+ }
19
+
20
+ function _toConsumableArray(r) {
21
+ return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
22
+ }
23
+
8
24
  function _objectWithoutPropertiesLoose(r, e) {
9
25
  if (null == r) return {};
10
26
  var t = {};
@@ -1,10 +1,26 @@
1
- import { d as _objectSpread2, r as raw, c as attrs, e as _toConsumableArray } from '../../dist/raw-0c1fab1c.worker.esm.js';
1
+ import { c as _arrayLikeToArray, b as _unsupportedIterableToArray } from '../../dist/slicedToArray-7d0170b6.worker.esm.js';
2
+ import { d as _objectSpread2, r as raw, c as attrs } from '../../dist/raw-eede220f.worker.esm.js';
2
3
  import React from 'react';
3
4
  import { jsx } from 'react/jsx-runtime';
4
- import '../../dist/slicedToArray-7d0170b6.worker.esm.js';
5
5
  import '@valbuild/core';
6
6
  import '@vercel/stega';
7
7
 
8
+ function _arrayWithoutHoles(r) {
9
+ if (Array.isArray(r)) return _arrayLikeToArray(r);
10
+ }
11
+
12
+ function _iterableToArray(r) {
13
+ if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
14
+ }
15
+
16
+ function _nonIterableSpread() {
17
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
18
+ }
19
+
20
+ function _toConsumableArray(r) {
21
+ return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
22
+ }
23
+
8
24
  function _objectWithoutPropertiesLoose(r, e) {
9
25
  if (null == r) return {};
10
26
  var t = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valbuild/react",
3
- "version": "0.125.0",
3
+ "version": "0.127.0",
4
4
  "private": false,
5
5
  "description": "Val - React internal helpers",
6
6
  "repository": {
@@ -11,9 +11,9 @@
11
11
  "dependencies": {
12
12
  "@vercel/stega": "^1.1.0",
13
13
  "base64-arraybuffer": "^1.0.2",
14
- "@valbuild/ui": "0.125.0",
15
- "@valbuild/core": "0.125.0",
16
- "@valbuild/shared": "0.125.0"
14
+ "@valbuild/core": "0.127.0",
15
+ "@valbuild/shared": "0.127.0",
16
+ "@valbuild/ui": "0.127.0"
17
17
  },
18
18
  "devDependencies": {
19
19
  "@testing-library/react": "^16.3.3",
@@ -1,6 +1,6 @@
1
1
  import { a as _typeof, _ as _slicedToArray } from '../../dist/slicedToArray-9cce0d9f.browser.esm.js';
2
- import { s as stegaDecodeStrings, _ as _createForOfIteratorHelper } from '../../dist/raw-76ccee5c.browser.esm.js';
3
- export { c as attrs, g as getModuleIds, r as raw, b as stegaClean, s as stegaDecodeStrings, a as stegaEncode } from '../../dist/raw-76ccee5c.browser.esm.js';
2
+ import { s as stegaDecodeStrings, _ as _createForOfIteratorHelper } from '../../dist/raw-57f19ada.browser.esm.js';
3
+ export { c as attrs, g as getModuleIds, r as raw, b as stegaClean, s as stegaDecodeStrings, a as stegaEncode } from '../../dist/raw-57f19ada.browser.esm.js';
4
4
  import ReactJSXRuntime__default from 'react/jsx-runtime';
5
5
  import jsxRuntimeDev__default from 'react/jsx-dev-runtime';
6
6
  import React from 'react';
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var slicedToArray = require('../../dist/slicedToArray-e9e8e991.cjs.dev.js');
6
- var raw = require('../../dist/raw-44cf5d7f.cjs.dev.js');
6
+ var raw = require('../../dist/raw-512e7a0a.cjs.dev.js');
7
7
  var ReactJSXRuntime = require('react/jsx-runtime');
8
8
  var jsxRuntimeDev = require('react/jsx-dev-runtime');
9
9
  var React = require('react');
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var slicedToArray = require('../../dist/slicedToArray-86004d59.cjs.prod.js');
6
- var raw = require('../../dist/raw-c75f7272.cjs.prod.js');
6
+ var raw = require('../../dist/raw-fe78b046.cjs.prod.js');
7
7
  var ReactJSXRuntime = require('react/jsx-runtime');
8
8
  var jsxRuntimeDev = require('react/jsx-dev-runtime');
9
9
  var React = require('react');
@@ -1,6 +1,6 @@
1
1
  import { a as _typeof, _ as _slicedToArray } from '../../dist/slicedToArray-0c0a3b4a.esm.js';
2
- import { s as stegaDecodeStrings, _ as _createForOfIteratorHelper } from '../../dist/raw-8453ef90.esm.js';
3
- export { c as attrs, g as getModuleIds, r as raw, b as stegaClean, s as stegaDecodeStrings, a as stegaEncode } from '../../dist/raw-8453ef90.esm.js';
2
+ import { s as stegaDecodeStrings, _ as _createForOfIteratorHelper } from '../../dist/raw-7ce61255.esm.js';
3
+ export { c as attrs, g as getModuleIds, r as raw, b as stegaClean, s as stegaDecodeStrings, a as stegaEncode } from '../../dist/raw-7ce61255.esm.js';
4
4
  import ReactJSXRuntime__default from 'react/jsx-runtime';
5
5
  import jsxRuntimeDev__default from 'react/jsx-dev-runtime';
6
6
  import React from 'react';
@@ -1,6 +1,6 @@
1
1
  import { a as _typeof, _ as _slicedToArray } from '../../dist/slicedToArray-7d0170b6.worker.esm.js';
2
- import { s as stegaDecodeStrings, _ as _createForOfIteratorHelper } from '../../dist/raw-0c1fab1c.worker.esm.js';
3
- export { c as attrs, g as getModuleIds, r as raw, b as stegaClean, s as stegaDecodeStrings, a as stegaEncode } from '../../dist/raw-0c1fab1c.worker.esm.js';
2
+ import { s as stegaDecodeStrings, _ as _createForOfIteratorHelper } from '../../dist/raw-eede220f.worker.esm.js';
3
+ export { c as attrs, g as getModuleIds, r as raw, b as stegaClean, s as stegaDecodeStrings, a as stegaEncode } from '../../dist/raw-eede220f.worker.esm.js';
4
4
  import ReactJSXRuntime__default from 'react/jsx-runtime';
5
5
  import jsxRuntimeDev__default from 'react/jsx-dev-runtime';
6
6
  import React from 'react';