@stapel/attributes-react 0.1.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.
Files changed (74) hide show
  1. package/README.md +123 -0
  2. package/dist/default/FeatureBadges.d.ts +33 -0
  3. package/dist/default/FeatureBadges.d.ts.map +1 -0
  4. package/dist/default/FeatureBadges.js +56 -0
  5. package/dist/default/FeatureBadges.js.map +1 -0
  6. package/dist/default/FeatureFields.d.ts +52 -0
  7. package/dist/default/FeatureFields.d.ts.map +1 -0
  8. package/dist/default/FeatureFields.js +60 -0
  9. package/dist/default/FeatureFields.js.map +1 -0
  10. package/dist/default/editors.d.ts +24 -0
  11. package/dist/default/editors.d.ts.map +1 -0
  12. package/dist/default/editors.js +354 -0
  13. package/dist/default/editors.js.map +1 -0
  14. package/dist/default/index.d.ts +27 -0
  15. package/dist/default/index.d.ts.map +1 -0
  16. package/dist/default/index.js +25 -0
  17. package/dist/default/index.js.map +1 -0
  18. package/dist/dto.d.ts +40 -0
  19. package/dist/dto.d.ts.map +1 -0
  20. package/dist/dto.js +64 -0
  21. package/dist/dto.js.map +1 -0
  22. package/dist/errors.d.ts +57 -0
  23. package/dist/errors.d.ts.map +1 -0
  24. package/dist/errors.js +98 -0
  25. package/dist/errors.js.map +1 -0
  26. package/dist/format.d.ts +46 -0
  27. package/dist/format.d.ts.map +1 -0
  28. package/dist/format.js +159 -0
  29. package/dist/format.js.map +1 -0
  30. package/dist/i18n/es.d.ts +13 -0
  31. package/dist/i18n/es.d.ts.map +1 -0
  32. package/dist/i18n/es.js +36 -0
  33. package/dist/i18n/es.js.map +1 -0
  34. package/dist/i18n/keys.d.ts +56 -0
  35. package/dist/i18n/keys.d.ts.map +1 -0
  36. package/dist/i18n/keys.js +80 -0
  37. package/dist/i18n/keys.js.map +1 -0
  38. package/dist/i18n/ru.d.ts +19 -0
  39. package/dist/i18n/ru.d.ts.map +1 -0
  40. package/dist/i18n/ru.js +42 -0
  41. package/dist/i18n/ru.js.map +1 -0
  42. package/dist/index.d.ts +58 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +54 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/registry.d.ts +122 -0
  47. package/dist/registry.d.ts.map +1 -0
  48. package/dist/registry.js +82 -0
  49. package/dist/registry.js.map +1 -0
  50. package/dist/types.d.ts +134 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +35 -0
  53. package/dist/types.js.map +1 -0
  54. package/dist/validate.d.ts +88 -0
  55. package/dist/validate.d.ts.map +1 -0
  56. package/dist/validate.js +410 -0
  57. package/dist/validate.js.map +1 -0
  58. package/manifest.json +96 -0
  59. package/package.json +107 -0
  60. package/src/default/FeatureBadges.tsx +123 -0
  61. package/src/default/FeatureFields.tsx +140 -0
  62. package/src/default/editors.tsx +578 -0
  63. package/src/default/index.ts +34 -0
  64. package/src/dto.ts +78 -0
  65. package/src/errors.ts +127 -0
  66. package/src/format.ts +210 -0
  67. package/src/i18n/es.ts +41 -0
  68. package/src/i18n/keys.ts +89 -0
  69. package/src/i18n/ru.ts +48 -0
  70. package/src/index.ts +98 -0
  71. package/src/registry.ts +167 -0
  72. package/src/types.ts +166 -0
  73. package/src/validate.ts +507 -0
  74. package/tsconfig.json +26 -0
@@ -0,0 +1,410 @@
1
+ import { featureConfig, featureName, featureType } from "./types.js";
2
+ import { ERROR_CODE_TO_KEY } from "./errors.js";
3
+ /** `stapel_attributes.types.hex_color.constants.SIMPLE_COLORS` — the closed
4
+ * set of colour categories a `hex_color` value must name. */
5
+ export const SIMPLE_COLORS = [
6
+ "black",
7
+ "white",
8
+ "gray",
9
+ "silver",
10
+ "red",
11
+ "pink",
12
+ "orange",
13
+ "yellow",
14
+ "green",
15
+ "blue",
16
+ "purple",
17
+ "brown",
18
+ "gold",
19
+ "beige",
20
+ "turquoise",
21
+ "clear",
22
+ "multicolor",
23
+ "custom",
24
+ ];
25
+ const HEX_PATTERN = /^#(?:[0-9a-fA-F]{3}){1,2}$/;
26
+ const TRUE_STRINGS = new Set(["true", "1", "yes", "on"]);
27
+ const FALSE_STRINGS = new Set(["false", "0", "no", "off"]);
28
+ /** Length in Unicode code points — the unit BOTH sides count in. */
29
+ export function codePointLength(text) {
30
+ return [...text].length;
31
+ }
32
+ /**
33
+ * Does `pattern` match the WHOLE of `text`? `re.fullmatch`, in JavaScript.
34
+ *
35
+ * A pattern JS cannot compile (a Python-only construct) is NOT the person's
36
+ * problem: the mirror stands down and lets the server, which compiled it, be
37
+ * the one to refuse. The `u` flag is tried first because it is what makes `.`
38
+ * and quantifiers count code points rather than surrogate halves, and dropped
39
+ * when a pattern is only valid without it.
40
+ */
41
+ export function patternFullMatch(pattern, text) {
42
+ const anchored = `^(?:${pattern})$`;
43
+ for (const flags of ["u", ""]) {
44
+ try {
45
+ return new RegExp(anchored, flags).test(text);
46
+ }
47
+ catch {
48
+ continue;
49
+ }
50
+ }
51
+ return undefined;
52
+ }
53
+ function num(config, key) {
54
+ const raw = config[key];
55
+ return typeof raw === "number" && Number.isFinite(raw) ? raw : undefined;
56
+ }
57
+ function list(config, key) {
58
+ const raw = config[key];
59
+ return Array.isArray(raw) ? raw : [];
60
+ }
61
+ /** An option's value, from either shape the engine's types allow (a bare
62
+ * scalar, or an object with `value`). */
63
+ function optionValue(option) {
64
+ if (option !== null && typeof option === "object" && "value" in option) {
65
+ return option.value;
66
+ }
67
+ return option;
68
+ }
69
+ /**
70
+ * "Nothing was entered" — the one shape the mandatory rule fires on, and the
71
+ * engine's own predicate: `raw_value is None or raw_value == '' or
72
+ * raw_value == []` (`validation.py`). An explicit `false` is an ANSWER for a
73
+ * `bool`, and `0` is an answer for an `int`, which is why this is not a
74
+ * falsiness check.
75
+ */
76
+ export function isBlank(value) {
77
+ if (value === undefined || value === null)
78
+ return true;
79
+ if (typeof value === "string")
80
+ return value === "";
81
+ if (Array.isArray(value))
82
+ return value.length === 0;
83
+ return false;
84
+ }
85
+ // ── per-type rules ───────────────────────────────────────────────────────────
86
+ function validateString(config, value) {
87
+ const text = typeof value === "string" ? value : String(value);
88
+ const length = codePointLength(text);
89
+ const minLength = num(config, "minLength");
90
+ const maxLength = num(config, "maxLength");
91
+ if (minLength !== undefined && length < minLength) {
92
+ return { code: "below_minimum", ref_value: minLength };
93
+ }
94
+ if (maxLength !== undefined && length > maxLength) {
95
+ return { code: "above_maximum", ref_value: maxLength };
96
+ }
97
+ const pattern = config["pattern"];
98
+ if (typeof pattern === "string" && pattern.length > 0) {
99
+ const matched = patternFullMatch(pattern, text);
100
+ if (matched === false)
101
+ return { code: "invalid_format", ref_value: pattern };
102
+ }
103
+ const options = list(config, "options");
104
+ // `allowCustom` absent means TRUE for `string` (the dataclass default), so
105
+ // an options list without an explicit `allowCustom: false` constrains
106
+ // nothing. Reading an absent key as "closed set" would refuse values the
107
+ // server accepts.
108
+ if (options.length > 0 && config["allowCustom"] === false) {
109
+ if (!options.some((option) => optionValue(option) === text)) {
110
+ return { code: "not_in_options", ref_value: [...options].map(optionValue) };
111
+ }
112
+ }
113
+ return undefined;
114
+ }
115
+ function validateNumber(config, value, isInt) {
116
+ const parsed = typeof value === "number" ? value : Number(value);
117
+ if (typeof value === "boolean" || !Number.isFinite(parsed)) {
118
+ return { code: "invalid_type" };
119
+ }
120
+ // `int`'s normalizer is Python's `int()`, which TRUNCATES toward zero
121
+ // rather than refusing a fractional input — so the range check runs on the
122
+ // truncated number, exactly as it does server-side.
123
+ const number = isInt ? Math.trunc(parsed) : parsed;
124
+ const min = num(config, "min");
125
+ const max = num(config, "max");
126
+ if (min !== undefined && number < min)
127
+ return { code: "below_minimum", ref_value: min };
128
+ if (max !== undefined && number > max)
129
+ return { code: "above_maximum", ref_value: max };
130
+ const options = list(config, "options");
131
+ if (options.length > 0 && config["allowCustom"] === false) {
132
+ const precision = isInt ? 0 : (num(config, "precision") ?? 2);
133
+ const round = (n) => Number(n.toFixed(precision));
134
+ if (!options.some((option) => round(Number(optionValue(option))) === round(number))) {
135
+ return { code: "not_in_options", ref_value: [...options].map(optionValue) };
136
+ }
137
+ }
138
+ return undefined;
139
+ }
140
+ function validateBool(value) {
141
+ if (typeof value === "boolean")
142
+ return undefined;
143
+ if (typeof value === "number")
144
+ return undefined; // bool(n), server-side
145
+ if (typeof value === "string") {
146
+ const lower = value.toLowerCase();
147
+ return TRUE_STRINGS.has(lower) || FALSE_STRINGS.has(lower)
148
+ ? undefined
149
+ : { code: "invalid_type" };
150
+ }
151
+ return { code: "invalid_type" };
152
+ }
153
+ function validateSelect(config, value) {
154
+ if (!Array.isArray(value))
155
+ return { code: "invalid_type" };
156
+ const minSelected = num(config, "minSelected") ?? 0;
157
+ const maxSelected = num(config, "maxSelected");
158
+ if (value.length < minSelected) {
159
+ return { code: "below_minimum", ref_value: minSelected };
160
+ }
161
+ if (maxSelected !== undefined && value.length > maxSelected) {
162
+ return { code: "above_maximum", ref_value: maxSelected };
163
+ }
164
+ if (new Set(value).size !== value.length)
165
+ return { code: "invalid_format" };
166
+ const allowed = list(config, "options").map((option) => optionValue(option));
167
+ for (const item of value) {
168
+ if (typeof item !== "string")
169
+ return { code: "invalid_type" };
170
+ if (!allowed.includes(item)) {
171
+ return {
172
+ code: "not_in_options",
173
+ ref_value: [...allowed].map(String).sort(),
174
+ };
175
+ }
176
+ }
177
+ return undefined;
178
+ }
179
+ function validateDate(config, value) {
180
+ // The engine's `normalize_dto` coerces int/float/numeric-string to an int
181
+ // and turns ANYTHING else into `None`, which its `validate_dto` then
182
+ // accepts. So a garbage date is silently dropped rather than refused — a
183
+ // known upstream wart, mirrored rather than "improved", because a mirror
184
+ // that refuses what the server accepts is a mirror that blocks a valid
185
+ // submit. (`stapel_attributes.types.date.type.DateFeatureType`.)
186
+ const timestamp = typeof value === "number" && Number.isFinite(value)
187
+ ? Math.trunc(value)
188
+ : typeof value === "string" && /^-?\d+$/.test(value.trim())
189
+ ? Number.parseInt(value.trim(), 10)
190
+ : undefined;
191
+ if (timestamp === undefined)
192
+ return undefined;
193
+ const now = Math.floor(Date.now() / 1000);
194
+ if (config["allowFuture"] === false && timestamp > now) {
195
+ return { code: "above_maximum", ref_value: now };
196
+ }
197
+ if (config["allowPast"] === false && timestamp < now) {
198
+ return { code: "below_minimum", ref_value: now };
199
+ }
200
+ const minDate = num(config, "minDate");
201
+ const maxDate = num(config, "maxDate");
202
+ if (minDate !== undefined && timestamp < minDate) {
203
+ return { code: "below_minimum", ref_value: minDate };
204
+ }
205
+ if (maxDate !== undefined && timestamp > maxDate) {
206
+ return { code: "above_maximum", ref_value: maxDate };
207
+ }
208
+ return undefined;
209
+ }
210
+ function validateHexColor(config, value) {
211
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
212
+ return { code: "invalid_type" };
213
+ }
214
+ const entry = value;
215
+ if (entry.hex !== undefined && entry.hex !== null) {
216
+ if (typeof entry.hex !== "string")
217
+ return { code: "invalid_type" };
218
+ const hex = entry.hex.trim();
219
+ if (hex.length > 0 && !HEX_PATTERN.test(hex))
220
+ return { code: "invalid_format" };
221
+ }
222
+ if (entry.simple === undefined || entry.simple === null || entry.simple === "") {
223
+ return { code: "invalid_format" };
224
+ }
225
+ if (typeof entry.simple !== "string")
226
+ return { code: "invalid_type" };
227
+ if (!SIMPLE_COLORS.includes(entry.simple)) {
228
+ return { code: "not_in_options", ref_value: [...SIMPLE_COLORS] };
229
+ }
230
+ const options = list(config, "options");
231
+ if (options.length > 0 && config["allowCustom"] !== true) {
232
+ const matched = options.some((option) => option !== null &&
233
+ typeof option === "object" &&
234
+ option.simple === entry.simple);
235
+ if (!matched) {
236
+ return {
237
+ code: "not_in_options",
238
+ ref_value: options.map((option) => option !== null && typeof option === "object"
239
+ ? option.simple
240
+ : option),
241
+ };
242
+ }
243
+ }
244
+ return undefined;
245
+ }
246
+ function findOption(options, value) {
247
+ for (const option of options) {
248
+ if (option !== null && typeof option === "object") {
249
+ if (option.value === value) {
250
+ return option;
251
+ }
252
+ }
253
+ else if (option === value) {
254
+ return {};
255
+ }
256
+ }
257
+ return undefined;
258
+ }
259
+ function validateHierarchicalSelect(config, value) {
260
+ if (!Array.isArray(value))
261
+ return { code: "invalid_type" };
262
+ if (value.length === 0)
263
+ return undefined; // the empty pre-check already ruled
264
+ const minDepth = num(config, "minDepth") ?? 1;
265
+ const maxDepth = num(config, "maxDepth");
266
+ if (value.length < minDepth)
267
+ return { code: "below_minimum", ref_value: minDepth };
268
+ if (maxDepth !== undefined && value.length > maxDepth) {
269
+ return { code: "above_maximum", ref_value: maxDepth };
270
+ }
271
+ let level = list(config, "options");
272
+ for (const step of value) {
273
+ if (typeof step !== "string")
274
+ return { code: "invalid_type" };
275
+ const option = findOption(level, step);
276
+ if (option === undefined) {
277
+ return { code: "not_in_options", ref_value: level.map(optionValue) };
278
+ }
279
+ level = Array.isArray(option.children) ? option.children : [];
280
+ }
281
+ return undefined;
282
+ }
283
+ function validateConvertibleUnit(config, dto) {
284
+ if (dto.value !== null && dto.value !== undefined) {
285
+ const parsed = typeof dto.value === "number" ? dto.value : Number(dto.value);
286
+ if (typeof dto.value === "boolean" || !Number.isFinite(parsed)) {
287
+ return { code: "invalid_type" };
288
+ }
289
+ }
290
+ const unit = dto["unit"];
291
+ if (unit === undefined || unit === null)
292
+ return undefined;
293
+ const allowed = [config["unit_m"], config["unit_i"]].filter((code) => typeof code === "string" && code.length > 0);
294
+ if (!allowed.includes(String(unit))) {
295
+ return { code: "not_in_options", ref_value: allowed };
296
+ }
297
+ // `min`/`max` are in the family's BASE unit and the conversion table is
298
+ // server-side — see this module's header.
299
+ return undefined;
300
+ }
301
+ /**
302
+ * Validate one submitted value against its feature's config. Returns the
303
+ * mirrored refusal, or `undefined` when this side of the wire is satisfied.
304
+ *
305
+ * `header` is never validated: the engine regenerates a header's DAO from its
306
+ * config and skips it outright in the batch validator, so a header has
307
+ * nothing to check and must never carry a value.
308
+ */
309
+ export function validateFeatureValue(feature, dto) {
310
+ const type = featureType(feature);
311
+ if (type === "header")
312
+ return undefined;
313
+ const config = featureConfig(feature);
314
+ if (isBlank(dto.value)) {
315
+ return feature.mandatory === true
316
+ ? failed(feature, { code: "mandatory_missing" })
317
+ : ok(feature);
318
+ }
319
+ const refusal = (() => {
320
+ switch (type) {
321
+ case "string":
322
+ return validateString(config, dto.value);
323
+ case "int":
324
+ return validateNumber(config, dto.value, true);
325
+ case "float":
326
+ return validateNumber(config, dto.value, false);
327
+ case "bool":
328
+ return validateBool(dto.value);
329
+ case "select":
330
+ return validateSelect(config, dto.value);
331
+ case "date":
332
+ return validateDate(config, dto.value);
333
+ case "hex_color":
334
+ return validateHexColor(config, dto.value);
335
+ case "hierarchical_select":
336
+ return validateHierarchicalSelect(config, dto.value);
337
+ case "convertible_unit":
338
+ return validateConvertibleUnit(config, dto);
339
+ default:
340
+ // An unknown type is the server's to judge — see the module header.
341
+ return undefined;
342
+ }
343
+ })();
344
+ return refusal === undefined ? ok(feature) : failed(feature, refusal);
345
+ }
346
+ function ok(feature) {
347
+ return {
348
+ slug: feature.slug,
349
+ status: "ok",
350
+ ...(feature.id === undefined || feature.id === null ? {} : { id: feature.id }),
351
+ };
352
+ }
353
+ function failed(feature, refusal) {
354
+ return {
355
+ slug: feature.slug,
356
+ status: "validation_failed",
357
+ error: refusal.code,
358
+ localizable_error: ERROR_CODE_TO_KEY[refusal.code],
359
+ // The engine's own params, verbatim: `{feature, slug}`. `field` is added
360
+ // later, by `featureErrorsBySlug`, so the mirror's rows and the server's
361
+ // rows go through the same one step.
362
+ params: { feature: featureName(feature), slug: feature.slug },
363
+ ...(feature.id === undefined || feature.id === null ? {} : { id: feature.id }),
364
+ ...(refusal.ref_value === undefined ? {} : { ref_value: refusal.ref_value }),
365
+ };
366
+ }
367
+ /**
368
+ * Validate a whole answer set against a category's features — the client-side
369
+ * twin of `POST /categories/{pk}/validate-dto/`.
370
+ *
371
+ * Mirrors the engine's two passes and their order, because the order is what
372
+ * a caller sees: first every SUBMITTED entry whose slug the category allows
373
+ * (an unknown slug is ignored, not refused — the engine's documented
374
+ * behaviour), then every allowed feature that was never submitted, of which
375
+ * only a mandatory non-header one produces a row.
376
+ */
377
+ export function mirrorValidate(features, dto) {
378
+ const bySlug = new Map();
379
+ for (const feature of features) {
380
+ bySlug.set(feature.slug, feature);
381
+ if (feature.id !== undefined && feature.id !== null) {
382
+ bySlug.set(String(feature.id), feature);
383
+ }
384
+ }
385
+ const results = [];
386
+ const seen = new Set();
387
+ for (const [key, entry] of Object.entries(dto)) {
388
+ const feature = bySlug.get(key);
389
+ if (feature === undefined)
390
+ continue; // unknown slug — ignored, per the engine
391
+ seen.add(feature.slug);
392
+ const result = validateFeatureValue(feature, entry);
393
+ if (result !== undefined)
394
+ results.push(result);
395
+ }
396
+ for (const feature of features) {
397
+ if (seen.has(feature.slug))
398
+ continue;
399
+ if (featureType(feature) === "header")
400
+ continue;
401
+ if (feature.mandatory !== true)
402
+ continue;
403
+ results.push(failed(feature, { code: "mandatory_missing" }));
404
+ }
405
+ return {
406
+ valid: results.every((result) => result.status === "ok"),
407
+ results,
408
+ };
409
+ }
410
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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"}
package/manifest.json ADDED
@@ -0,0 +1,96 @@
1
+ {
2
+ "$generated": "hand-authored, not scripts/gen-manifest.mjs (that driver derives backend.contract from a sibling Django module's docs/schema.json + pyproject.toml; stapel-attributes is an L1 library with NO HTTP surface and emits neither — see backend below)",
3
+ "package": "@stapel/attributes-react",
4
+ "version": "0.1.0",
5
+ "backend": {
6
+ "module": "stapel-attributes",
7
+ "kind": "L1 library, no HTTP surface",
8
+ "contract": null,
9
+ "pin": "test/fixtures/attributes-registry.json — the builtin type set and the ValidationErrorCode vocabulary, taken from the engine's own tests/golden/ corpora and asserted by test/contract.test.ts"
10
+ },
11
+ "layers": ["headless", "default", "i18n"],
12
+ "axis": "config.type — the VALUE type of an attribute. NOT FormField.kind, which is the admin config form's field kind and is what @stapel/forms-react keys on.",
13
+ "valueTypes": [
14
+ "bool",
15
+ "convertible_unit",
16
+ "date",
17
+ "float",
18
+ "header",
19
+ "hex_color",
20
+ "hierarchical_select",
21
+ "int",
22
+ "select",
23
+ "string"
24
+ ],
25
+ "exports": {
26
+ "runtime": [
27
+ "registerValueEditor",
28
+ "unregisterValueEditor",
29
+ "resolveValueEditor",
30
+ "registeredValueEditorTypes",
31
+ "unsupportedTypes",
32
+ "unsupportedTypeGate",
33
+ "UNTYPED_FEATURE",
34
+ "mirrorValidate",
35
+ "validateFeatureValue",
36
+ "isBlank",
37
+ "codePointLength",
38
+ "patternFullMatch",
39
+ "SIMPLE_COLORS",
40
+ "toFeaturesDto",
41
+ "fromFeaturesDto",
42
+ "formatFeatureValue",
43
+ "hexColorSwatch",
44
+ "FORMATTABLE_TYPES",
45
+ "featureType",
46
+ "featureConfig",
47
+ "featureName",
48
+ "featureErrorsBySlug",
49
+ "resultErrorKey",
50
+ "ERROR_CODE_TO_KEY",
51
+ "VALIDATION_ERROR_CODES",
52
+ "ATTRIBUTES_I18N_KEYS",
53
+ "ATTRIBUTES_ERROR_BUNDLE_EN",
54
+ "attributesI18nBundleEn",
55
+ "registerAttributesI18n",
56
+ "BUILTIN_VALUE_EDITORS",
57
+ "BUILTIN_VALUE_EDITOR_TYPES",
58
+ "FeatureFields",
59
+ "UnsupportedValueEditor",
60
+ "featureControlId",
61
+ "FeatureBadges",
62
+ "FeatureValueList",
63
+ "timestampToInputValue",
64
+ "inputValueToTimestamp"
65
+ ],
66
+ "types": [
67
+ "FeatureDef",
68
+ "FeatureConfig",
69
+ "FeatureValueDto",
70
+ "FeaturesDto",
71
+ "FeatureValidationResult",
72
+ "ValidationBatchResult",
73
+ "ValidationErrorCode",
74
+ "ValidationStatus",
75
+ "ValueEditor",
76
+ "ValueEditorProps",
77
+ "FormatOptions",
78
+ "AttributesI18nKey",
79
+ "FeatureFieldsProps",
80
+ "FeatureRowProps",
81
+ "FeatureDisplayProps",
82
+ "UnsupportedValueEditorProps"
83
+ ]
84
+ },
85
+ "i18nKeys": [
86
+ "attributes.unsupported_type",
87
+ "attributes.submit.blocked.unsupported_type",
88
+ "attributes.untyped_feature",
89
+ "attributes.value.not_set",
90
+ "attributes.value.unreadable",
91
+ "attributes.bool.yes",
92
+ "attributes.bool.no",
93
+ "attributes.select.placeholder",
94
+ "attributes.required"
95
+ ]
96
+ }
package/package.json ADDED
@@ -0,0 +1,107 @@
1
+ {
2
+ "name": "@stapel/attributes-react",
3
+ "version": "0.1.0",
4
+ "description": "React value layer for stapel-attributes' dynamic feature types: a value-editor registry keyed on config.type (explicit registration > skin builtin > loud unsupported notice, with the submit blocked and the reason named), a client-side validation mirror that speaks the engine's own error.400.feature_* keys (pattern as fullmatch, string length in Unicode code points), DTO helpers for the {slug: {type, value}} wire shape, and display formatting. Zero visual opinion in the main entry; an opt-in /default subpath ships the antd editors for all ten builtin types plus <FeatureFields> and <FeatureBadges>.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/usestapel/stapel-react.git",
9
+ "directory": "packages/attributes-react"
10
+ },
11
+ "type": "module",
12
+ "sideEffects": false,
13
+ "main": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/index.d.ts",
18
+ "default": "./dist/index.js"
19
+ },
20
+ "./default": {
21
+ "types": "./dist/default/index.d.ts",
22
+ "default": "./dist/default/index.js"
23
+ },
24
+ "./i18n/ru": {
25
+ "types": "./dist/i18n/ru.d.ts",
26
+ "default": "./dist/i18n/ru.js"
27
+ },
28
+ "./i18n/es": {
29
+ "types": "./dist/i18n/es.d.ts",
30
+ "default": "./dist/i18n/es.js"
31
+ },
32
+ "./manifest": "./manifest.json",
33
+ "./manifest.json": "./manifest.json",
34
+ "./package.json": "./package.json"
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "src",
39
+ "tsconfig.json",
40
+ "README.md",
41
+ "manifest.json"
42
+ ],
43
+ "scripts": {
44
+ "build": "tsc -p tsconfig.json",
45
+ "test": "tsc -p tsconfig.test.json && vitest run",
46
+ "lint": "eslint .",
47
+ "size": "size-limit"
48
+ },
49
+ "size-limit": [
50
+ {
51
+ "name": "index — the registry + mirror + DTO helpers must stay React-only: no antd",
52
+ "path": "dist/index.js",
53
+ "limit": "8 KB"
54
+ },
55
+ {
56
+ "name": "default — the antd value editors must stay out of the main bundle",
57
+ "path": "dist/default/index.js",
58
+ "limit": "14 KB"
59
+ },
60
+ {
61
+ "name": "i18n/ru — the Russian bundle is opt-in, not carried by the main entry",
62
+ "path": "dist/i18n/ru.js",
63
+ "limit": "3 KB"
64
+ },
65
+ {
66
+ "name": "i18n/es — the Spanish bundle is opt-in, not carried by the main entry",
67
+ "path": "dist/i18n/es.js",
68
+ "limit": "3 KB"
69
+ }
70
+ ],
71
+ "peerDependencies": {
72
+ "@stapel/core": ">=0.14.0 <1.0.0",
73
+ "@stapel/tokens-antd": ">=0.5.0",
74
+ "antd": ">=5.20.0 <7",
75
+ "react": ">=19"
76
+ },
77
+ "peerDependenciesMeta": {
78
+ "@stapel/tokens-antd": {
79
+ "optional": true
80
+ },
81
+ "antd": {
82
+ "optional": true
83
+ }
84
+ },
85
+ "devDependencies": {
86
+ "@size-limit/preset-small-lib": "^11.2.0",
87
+ "@stapel/core": "workspace:^",
88
+ "@stapel/tokens": "workspace:^",
89
+ "@stapel/tokens-antd": "workspace:^",
90
+ "@testing-library/react": "^16.3.0",
91
+ "@types/react": "^19.1.0",
92
+ "@types/react-dom": "^19.1.0",
93
+ "antd": "^6.5.0",
94
+ "jsdom": "^26.1.0",
95
+ "react": "^19.1.0",
96
+ "react-dom": "^19.1.0",
97
+ "size-limit": "^11.2.0",
98
+ "typescript": "^5.8.3",
99
+ "vitest": "^3.2.4"
100
+ },
101
+ "engines": {
102
+ "node": ">=22"
103
+ },
104
+ "publishConfig": {
105
+ "access": "public"
106
+ }
107
+ }