@stapel/vocabularies-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 (130) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/LICENSE +21 -0
  3. package/MODULE.md +92 -0
  4. package/README.md +173 -0
  5. package/dist/api/extensions.d.ts +8 -0
  6. package/dist/api/extensions.d.ts.map +1 -0
  7. package/dist/api/extensions.js +8 -0
  8. package/dist/api/extensions.js.map +1 -0
  9. package/dist/api/generated/schema.d.ts +234 -0
  10. package/dist/api/generated/schema.d.ts.map +1 -0
  11. package/dist/api/generated/schema.js +2 -0
  12. package/dist/api/generated/schema.js.map +1 -0
  13. package/dist/api/types.d.ts +23 -0
  14. package/dist/api/types.d.ts.map +1 -0
  15. package/dist/api/types.js +2 -0
  16. package/dist/api/types.js.map +1 -0
  17. package/dist/api/vocabulariesApi.d.ts +14 -0
  18. package/dist/api/vocabulariesApi.d.ts.map +1 -0
  19. package/dist/api/vocabulariesApi.js +4 -0
  20. package/dist/api/vocabulariesApi.js.map +1 -0
  21. package/dist/client.d.ts +49 -0
  22. package/dist/client.d.ts.map +1 -0
  23. package/dist/client.js +118 -0
  24. package/dist/client.js.map +1 -0
  25. package/dist/default/VocabularyTermSelect.d.ts +24 -0
  26. package/dist/default/VocabularyTermSelect.d.ts.map +1 -0
  27. package/dist/default/VocabularyTermSelect.js +75 -0
  28. package/dist/default/VocabularyTermSelect.js.map +1 -0
  29. package/dist/default/index.d.ts +16 -0
  30. package/dist/default/index.d.ts.map +1 -0
  31. package/dist/default/index.js +14 -0
  32. package/dist/default/index.js.map +1 -0
  33. package/dist/default/types.d.ts +12 -0
  34. package/dist/default/types.d.ts.map +1 -0
  35. package/dist/default/types.js +2 -0
  36. package/dist/default/types.js.map +1 -0
  37. package/dist/flows/errors.d.ts +12 -0
  38. package/dist/flows/errors.d.ts.map +1 -0
  39. package/dist/flows/errors.js +13 -0
  40. package/dist/flows/errors.js.map +1 -0
  41. package/dist/flows/registry.d.ts +22 -0
  42. package/dist/flows/registry.d.ts.map +1 -0
  43. package/dist/flows/registry.js +20 -0
  44. package/dist/flows/registry.js.map +1 -0
  45. package/dist/headless/VocabulariesProvider.d.ts +19 -0
  46. package/dist/headless/VocabulariesProvider.d.ts.map +1 -0
  47. package/dist/headless/VocabulariesProvider.js +15 -0
  48. package/dist/headless/VocabulariesProvider.js.map +1 -0
  49. package/dist/i18n/errorsMap.d.ts +10 -0
  50. package/dist/i18n/errorsMap.d.ts.map +1 -0
  51. package/dist/i18n/errorsMap.js +20 -0
  52. package/dist/i18n/errorsMap.js.map +1 -0
  53. package/dist/i18n/es.d.ts +21 -0
  54. package/dist/i18n/es.d.ts.map +1 -0
  55. package/dist/i18n/es.js +38 -0
  56. package/dist/i18n/es.js.map +1 -0
  57. package/dist/i18n/generated/errors.es.gen.d.ts +16 -0
  58. package/dist/i18n/generated/errors.es.gen.d.ts.map +1 -0
  59. package/dist/i18n/generated/errors.es.gen.js +58 -0
  60. package/dist/i18n/generated/errors.es.gen.js.map +1 -0
  61. package/dist/i18n/generated/errors.gen.d.ts +305 -0
  62. package/dist/i18n/generated/errors.gen.d.ts.map +1 -0
  63. package/dist/i18n/generated/errors.gen.js +156 -0
  64. package/dist/i18n/generated/errors.gen.js.map +1 -0
  65. package/dist/i18n/generated/errors.ru.gen.d.ts +16 -0
  66. package/dist/i18n/generated/errors.ru.gen.d.ts.map +1 -0
  67. package/dist/i18n/generated/errors.ru.gen.js +58 -0
  68. package/dist/i18n/generated/errors.ru.gen.js.map +1 -0
  69. package/dist/i18n/keys.d.ts +33 -0
  70. package/dist/i18n/keys.d.ts.map +1 -0
  71. package/dist/i18n/keys.js +44 -0
  72. package/dist/i18n/keys.js.map +1 -0
  73. package/dist/i18n/ru.d.ts +26 -0
  74. package/dist/i18n/ru.d.ts.map +1 -0
  75. package/dist/i18n/ru.js +43 -0
  76. package/dist/i18n/ru.js.map +1 -0
  77. package/dist/index.d.ts +34 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +38 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/model/context.d.ts +11 -0
  82. package/dist/model/context.d.ts.map +1 -0
  83. package/dist/model/context.js +16 -0
  84. package/dist/model/context.js.map +1 -0
  85. package/dist/model/queryKeys.d.ts +5 -0
  86. package/dist/model/queryKeys.d.ts.map +1 -0
  87. package/dist/model/queryKeys.js +28 -0
  88. package/dist/model/queryKeys.js.map +1 -0
  89. package/dist/model/runtime.d.ts +17 -0
  90. package/dist/model/runtime.d.ts.map +1 -0
  91. package/dist/model/runtime.js +6 -0
  92. package/dist/model/runtime.js.map +1 -0
  93. package/dist/model/useTermLabels.d.ts +26 -0
  94. package/dist/model/useTermLabels.d.ts.map +1 -0
  95. package/dist/model/useTermLabels.js +58 -0
  96. package/dist/model/useTermLabels.js.map +1 -0
  97. package/dist/model/useTermSearch.d.ts +24 -0
  98. package/dist/model/useTermSearch.d.ts.map +1 -0
  99. package/dist/model/useTermSearch.js +85 -0
  100. package/dist/model/useTermSearch.js.map +1 -0
  101. package/llms.txt +79 -0
  102. package/manifest.json +466 -0
  103. package/package.json +108 -0
  104. package/src/analytics/generated/events.json +7 -0
  105. package/src/api/extensions.ts +7 -0
  106. package/src/api/generated/schema.ts +236 -0
  107. package/src/api/types.ts +27 -0
  108. package/src/api/vocabulariesApi.ts +17 -0
  109. package/src/client.ts +176 -0
  110. package/src/default/VocabularyTermSelect.tsx +147 -0
  111. package/src/default/index.ts +15 -0
  112. package/src/default/types.ts +11 -0
  113. package/src/flows/errors.ts +16 -0
  114. package/src/flows/registry.ts +32 -0
  115. package/src/headless/VocabulariesProvider.tsx +20 -0
  116. package/src/i18n/errorsMap.ts +31 -0
  117. package/src/i18n/es.ts +49 -0
  118. package/src/i18n/generated/errors.es.gen.ts +64 -0
  119. package/src/i18n/generated/errors.gen.ts +187 -0
  120. package/src/i18n/generated/errors.json +351 -0
  121. package/src/i18n/generated/errors.ru.gen.ts +64 -0
  122. package/src/i18n/keys.ts +53 -0
  123. package/src/i18n/ru.ts +54 -0
  124. package/src/index.ts +92 -0
  125. package/src/model/context.tsx +28 -0
  126. package/src/model/queryKeys.ts +35 -0
  127. package/src/model/runtime.ts +25 -0
  128. package/src/model/useTermLabels.ts +72 -0
  129. package/src/model/useTermSearch.ts +118 -0
  130. package/tsconfig.json +26 -0
@@ -0,0 +1,14 @@
1
+ import type { StapelClient } from "@stapel/core";
2
+ /**
3
+ * The pair's typed operation surface. Today a thin holder over the injected
4
+ * {@link StapelClient}; the named, typed operations (`vocabularies.<op>()`) will
5
+ * be GENERATED from schema.json operationIds by gen-api v2 (task
6
+ * `core-typed-ops`). Until then add hand-authored operations here and put
7
+ * anything that can never be derived from the schema in `api/extensions.ts`,
8
+ * each flagged with WHY the codegen does not cover it.
9
+ */
10
+ export interface VocabulariesApi {
11
+ readonly client: StapelClient;
12
+ }
13
+ export declare function createVocabulariesApi(client: StapelClient): VocabulariesApi;
14
+ //# sourceMappingURL=vocabulariesApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vocabulariesApi.d.ts","sourceRoot":"","sources":["../../src/api/vocabulariesApi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;CAC/B;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,eAAe,CAE3E"}
@@ -0,0 +1,4 @@
1
+ export function createVocabulariesApi(client) {
2
+ return { client };
3
+ }
4
+ //# sourceMappingURL=vocabulariesApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vocabulariesApi.js","sourceRoot":"","sources":["../../src/api/vocabulariesApi.ts"],"names":[],"mappings":"AAcA,MAAM,UAAU,qBAAqB,CAAC,MAAoB;IACxD,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC"}
@@ -0,0 +1,49 @@
1
+ /** One term of a vocabulary level, as `GET …/terms/` returns it.
2
+ *
3
+ * A structural twin of `@stapel/attributes-react`'s `VocabularyTerm` — the same
4
+ * three fields, `has_children` spelled the wire's way. The declaration is not
5
+ * shared because the two packages must not import each other; the assignment
6
+ * is proven by `test/clientShape.test.ts`. */
7
+ export interface VocabularyTerm {
8
+ readonly code: string;
9
+ readonly label: string;
10
+ readonly has_children?: boolean;
11
+ }
12
+ /**
13
+ * The seam `@stapel/attributes-react` declares and this package implements.
14
+ *
15
+ * ATTRIBUTES-REACT OWNS THIS SHAPE. The copy here exists so a host can name
16
+ * the type without depending on the attributes pair, and
17
+ * `test/clientShape.test.ts` holds a third, hand-transcribed copy of the
18
+ * upstream declaration that the value returned below is assigned to — so a
19
+ * drift in either package is a red build here rather than a runtime hole in a
20
+ * storefront that wired the two together.
21
+ */
22
+ export interface VocabularyClient {
23
+ /** Terms of one level, narrowed by `query` and — when the caller has a
24
+ * parent term — by that term's code. An empty `query` means "the first page
25
+ * of this level", which is what a dropdown opens on. `signal` is honoured. */
26
+ search(vocabulary: string, level: string, query: string, parent?: string, signal?: AbortSignal): Promise<readonly VocabularyTerm[]>;
27
+ /** `{code: label}` for codes already stored somewhere. Unknown codes are
28
+ * omitted by the server, so a caller falls back to the code itself. */
29
+ resolve(vocabulary: string, level: string, codes: readonly string[]): Promise<Readonly<Record<string, string>>>;
30
+ }
31
+ export interface CreateVocabularyClientOptions {
32
+ /** Where stapel-vocabularies is mounted, e.g. `/vocabularies/api/v1/` or an
33
+ * absolute origin. A missing trailing slash is added. */
34
+ readonly baseUrl: string;
35
+ /** Transport override — a host's authenticated/instrumented `fetch`.
36
+ * Defaults to the global one. */
37
+ readonly fetch?: typeof globalThis.fetch;
38
+ /** Page size for {@link VocabularyClient.search}; the server caps it at 200
39
+ * and defaults to 50. */
40
+ readonly limit?: number;
41
+ }
42
+ /** The page a typeahead opens on. Matches the server's own default, so the
43
+ * parameter is sent for explicitness rather than to change behaviour. */
44
+ export declare const DEFAULT_TERM_LIMIT = 50;
45
+ /** The server refuses more than this many codes per resolve, and silently
46
+ * ignores the tail — so the client splits instead of losing labels. */
47
+ export declare const RESOLVE_BATCH = 200;
48
+ export declare function createVocabularyClient(options: CreateVocabularyClientOptions): VocabularyClient;
49
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AA4BA;;;;;8CAK8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;kFAE8E;IAC9E,MAAM,CACJ,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAAC;IACtC;2EACuE;IACvE,OAAO,CACL,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,6BAA6B;IAC5C;6DACyD;IACzD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;qCACiC;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IACzC;6BACyB;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;yEACyE;AACzE,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC;uEACuE;AACvE,eAAO,MAAM,aAAa,MAAM,CAAC;AAsBjC,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,6BAA6B,GACrC,gBAAgB,CA+DlB"}
package/dist/client.js ADDED
@@ -0,0 +1,118 @@
1
+ /**
2
+ * `createVocabularyClient` — the two reads a ref feature needs, over the
3
+ * stapel-vocabularies wire.
4
+ *
5
+ * ── Why this is a bare `fetch` client and not the pair's StapelClient ───────
6
+ *
7
+ * A `ref_select` reaches its terms through a seam
8
+ * (`VocabularyClient`) that `@stapel/attributes-react` DECLARES and this
9
+ * package SATISFIES — structurally, without either importing the other, so two
10
+ * L2 pairs stay independently releasable. The seam is two async functions and
11
+ * nothing else: no query client, no auth runtime, no provider. Anything this
12
+ * function returned that needed React context could not be handed to
13
+ * `<VocabularyClientProvider value={…}>` at a container's composition root,
14
+ * which is the one call site the seam exists for.
15
+ *
16
+ * Both endpoints are public reads (`ReadOnlyOrStaff`, ETag'd on the
17
+ * vocabulary's revision, no session), so there is no token to carry and
18
+ * nothing for the auth interceptors to do. A host that DOES need headers
19
+ * passes its own `fetch`.
20
+ *
21
+ * The caching the seam deliberately leaves out lives in this package's hooks
22
+ * (`useTermLabels` is a TanStack query; `useTermSearch` supersedes in flight),
23
+ * not in the client — a raw client is what makes the seam testable and what
24
+ * lets a host wrap it.
25
+ */
26
+ import { toStapelApiError } from "@stapel/core";
27
+ /** The page a typeahead opens on. Matches the server's own default, so the
28
+ * parameter is sent for explicitness rather than to change behaviour. */
29
+ export const DEFAULT_TERM_LIMIT = 50;
30
+ /** The server refuses more than this many codes per resolve, and silently
31
+ * ignores the tail — so the client splits instead of losing labels. */
32
+ export const RESOLVE_BATCH = 200;
33
+ function withSlash(baseUrl) {
34
+ return baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
35
+ }
36
+ /**
37
+ * `{code: label}` out of a body typed as `Record<string, unknown>` (the
38
+ * contract declares `additionalProperties: {}`). Non-string values are
39
+ * dropped rather than stringified: a label that is not a string is a server
40
+ * the caller should fall back from, and `"[object Object]"` in a dropdown is
41
+ * worse than the code.
42
+ */
43
+ function labelsOf(body) {
44
+ const out = {};
45
+ if (typeof body !== "object" || body === null)
46
+ return out;
47
+ for (const [code, label] of Object.entries(body)) {
48
+ if (typeof label === "string")
49
+ out[code] = label;
50
+ }
51
+ return out;
52
+ }
53
+ export function createVocabularyClient(options) {
54
+ const base = withSlash(options.baseUrl);
55
+ const doFetch = options.fetch ?? globalThis.fetch;
56
+ const limit = options.limit ?? DEFAULT_TERM_LIMIT;
57
+ async function read(url, signal) {
58
+ let response;
59
+ try {
60
+ response = await doFetch(url, {
61
+ method: "GET",
62
+ headers: { accept: "application/json" },
63
+ ...(signal !== undefined ? { signal } : {}),
64
+ });
65
+ }
66
+ catch (cause) {
67
+ // An abort is the CALLER's decision, not a failure: rethrow it as-is so
68
+ // `signal.aborted` still discriminates it. Folding it into the error
69
+ // dialect would make a superseded keystroke look like a dead backend.
70
+ if (signal?.aborted === true)
71
+ throw cause;
72
+ throw toStapelApiError(cause);
73
+ }
74
+ if (!response.ok) {
75
+ // One dialect at the single rethrow point (core `errors.ts`): the body is
76
+ // the backend's envelope, the status is the response's.
77
+ const body = await response.json().catch(() => undefined);
78
+ throw toStapelApiError(body, response.status);
79
+ }
80
+ return await response.json();
81
+ }
82
+ return {
83
+ async search(vocabulary, level, query, parent, signal) {
84
+ const params = new URLSearchParams();
85
+ params.set("level", level);
86
+ // OMITTED, not empty: `parent=` would ask the server for the children of
87
+ // a term whose code is the empty string, which is a level with nothing in
88
+ // it — the opposite of "the whole level", which is what no parent means.
89
+ if (parent !== undefined && parent.length > 0)
90
+ params.set("parent", parent);
91
+ params.set("q", query);
92
+ params.set("limit", String(limit));
93
+ const url = `${base}vocabularies/${encodeURIComponent(vocabulary)}/terms/?${params.toString()}`;
94
+ const page = (await read(url, signal));
95
+ const results = page?.results ?? [];
96
+ return results.map((term) => ({
97
+ code: term.code,
98
+ label: term.label,
99
+ has_children: term.has_children,
100
+ }));
101
+ },
102
+ async resolve(vocabulary, level, codes) {
103
+ const wanted = codes.filter((code) => code.length > 0);
104
+ if (wanted.length === 0)
105
+ return {};
106
+ const out = {};
107
+ for (let at = 0; at < wanted.length; at += RESOLVE_BATCH) {
108
+ const params = new URLSearchParams();
109
+ params.set("level", level);
110
+ params.set("codes", wanted.slice(at, at + RESOLVE_BATCH).join(","));
111
+ const url = `${base}vocabularies/${encodeURIComponent(vocabulary)}/terms/resolve/?${params.toString()}`;
112
+ Object.assign(out, labelsOf(await read(url)));
113
+ }
114
+ return out;
115
+ },
116
+ };
117
+ }
118
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { ReactElement } from "react";
2
+ import type { VocabularyClient } from "../client.js";
3
+ import type { ThemeModeProp } from "./types.js";
4
+ export interface VocabularyTermSelectProps extends ThemeModeProp {
5
+ /** The seam. `null` draws the unavailable notice — see the module header. */
6
+ readonly client: VocabularyClient | null;
7
+ readonly vocabulary: string;
8
+ readonly level: string;
9
+ /** Code of a term at the level above; narrows the list to its children. */
10
+ readonly parent?: string | undefined;
11
+ /** The codes currently chosen. Always a list, even single-select — a term
12
+ * value is a list on the wire. */
13
+ readonly value?: readonly string[] | undefined;
14
+ readonly onChange?: ((codes: readonly string[]) => void) | undefined;
15
+ /** Several terms at once (a facet filter); default is one. */
16
+ readonly multiple?: boolean | undefined;
17
+ /** Upper bound for a multiple select. */
18
+ readonly maxCount?: number | undefined;
19
+ readonly disabled?: boolean | undefined;
20
+ readonly id?: string | undefined;
21
+ readonly status?: "error" | "warning" | undefined;
22
+ }
23
+ export declare function VocabularyTermSelect(props: VocabularyTermSelectProps): ReactElement;
24
+ //# sourceMappingURL=VocabularyTermSelect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VocabularyTermSelect.d.ts","sourceRoot":"","sources":["../../src/default/VocabularyTermSelect.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAI1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,yBAA0B,SAAQ,aAAa;IAC9D,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC;sCACkC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACrE,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,yCAAyC;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;CACnD;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,yBAAyB,GAC/B,YAAY,CAuFd"}
@@ -0,0 +1,75 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * `<VocabularyTermSelect/>` — one vocabulary level as a typeahead.
4
+ *
5
+ * The SAME control `@stapel/attributes-react`'s `ref_select` editor draws,
6
+ * shipped on its own so the places a composer is not — a facet filter, an
7
+ * admin form, a bulk-edit row — do not each grow their own. The two are
8
+ * deliberately separate components rather than one imported across the seam:
9
+ * the editor's props are the attributes value-editor contract (a `FeatureDef`,
10
+ * `siblings`, a rule-narrowed config) and this one's are a vocabulary pointer,
11
+ * and collapsing them would make the two L2 pairs depend on each other for a
12
+ * hundred lines of antd.
13
+ *
14
+ * What it owes a person, and where each part lives:
15
+ *
16
+ * - the options ARE the answer to the current query, so `filterOption={false}`
17
+ * — letting antd filter them again would hide rows the server deliberately
18
+ * ranked (a prefix match first, a label matched in another language);
19
+ * - typing is debounced and superseding (`useTermSearch`);
20
+ * - a code the control already HOLDS is resolved to its label
21
+ * (`useTermLabels`) and kept in the option list even when the current page
22
+ * does not contain it — otherwise reopening a saved filter would silently
23
+ * empty the control;
24
+ * - no client is a LOUD state, not an empty dropdown: a control that cannot
25
+ * reach its terms and looks like one that found none is how a person ends
26
+ * up unable to answer a question nobody told them was broken.
27
+ */
28
+ import { useMemo } from "react";
29
+ import { Alert, Select } from "antd";
30
+ import { useT } from "@stapel/core";
31
+ import { SkinTheme } from "@stapel/tokens-antd/skin";
32
+ import { useTermSearch } from "../model/useTermSearch.js";
33
+ import { useTermLabels, termLabel } from "../model/useTermLabels.js";
34
+ import { VOCABULARIES_I18N_KEYS } from "../i18n/keys.js";
35
+ export function VocabularyTermSelect(props) {
36
+ const t = useT();
37
+ const { client, vocabulary, level, parent } = props;
38
+ const codes = useMemo(() => (props.value ?? []).filter((code) => code.length > 0), [props.value]);
39
+ const { terms, loading, search, open } = useTermSearch(client, {
40
+ vocabulary,
41
+ level,
42
+ parent,
43
+ });
44
+ const labels = useTermLabels(client, { vocabulary, level, codes });
45
+ // A held code the current page does not contain still has to be visible and
46
+ // pickable, so it is prepended rather than looked up in `terms`.
47
+ const options = useMemo(() => [
48
+ ...codes
49
+ .filter((code) => !terms.some((term) => term.code === code))
50
+ .map((code) => ({ value: code, label: termLabel(labels, code) })),
51
+ ...terms.map((term) => ({ value: term.code, label: term.label })),
52
+ ], [codes, terms, labels]);
53
+ if (client === null || vocabulary.length === 0 || level.length === 0) {
54
+ return (_jsx(SkinTheme, { surface: "bare", ...(props.mode !== undefined ? { mode: props.mode } : {}), children: _jsx(Alert, { type: "warning", showIcon: true, "data-testid": "vocabulary-term-select-unavailable", title: t(VOCABULARIES_I18N_KEYS.termSelectUnavailableTitle), description: t(VOCABULARIES_I18N_KEYS.termSelectUnavailable) }) }));
55
+ }
56
+ const multiple = props.multiple === true;
57
+ const onChange = props.onChange;
58
+ return (_jsx(SkinTheme, { surface: "bare", ...(props.mode !== undefined ? { mode: props.mode } : {}), children: _jsx(Select, { ...(props.id !== undefined ? { id: props.id } : {}), "data-testid": "vocabulary-term-select", style: { width: "100%" }, showSearch: true, filterOption: false, options: options, loading: loading, disabled: props.disabled === true, ...(props.status !== undefined ? { status: props.status } : {}), ...(multiple ? { mode: "multiple" } : {}), ...(multiple && props.maxCount !== undefined
59
+ ? { maxCount: props.maxCount }
60
+ : {}), placeholder: t(VOCABULARIES_I18N_KEYS.termSelectPlaceholder),
61
+ // `null` while loading, so antd draws its own spinner instead of
62
+ // saying "no matches" about a question that has not been answered yet.
63
+ notFoundContent: loading ? null : t(VOCABULARIES_I18N_KEYS.termSelectNoMatches), value: multiple ? codes : (codes[0] ?? null), onDropdownVisibleChange: (visible) => {
64
+ if (visible)
65
+ open();
66
+ }, onSearch: search, onChange: (next) => {
67
+ const picked = next === null || next === undefined
68
+ ? []
69
+ : Array.isArray(next)
70
+ ? [...next]
71
+ : [next];
72
+ onChange?.(picked.filter((code) => code.length > 0));
73
+ } }) }));
74
+ }
75
+ //# sourceMappingURL=VocabularyTermSelect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VocabularyTermSelect.js","sourceRoot":"","sources":["../../src/default/VocabularyTermSelect.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `@stapel/vocabularies-react/default` — the pair's default AntD skin (§54: a pair ships a
3
+ * FEATURE, not only a bag). A separate entry point, so a host that brings its
4
+ * own visuals never pulls `antd` or the token bridge into its bundle;
5
+ * importing this subpath is the opt-in.
6
+ *
7
+ * ```tsx
8
+ * import { VocabularyTermSelect } from "@stapel/vocabularies-react/default";
9
+ * // under core's <I18nProvider>; the client is a prop, not a context read:
10
+ * <VocabularyTermSelect client={client} vocabulary="avito-phones" level="Vendor" … />
11
+ * ```
12
+ */
13
+ export { VocabularyTermSelect } from "./VocabularyTermSelect.js";
14
+ export type { VocabularyTermSelectProps } from "./VocabularyTermSelect.js";
15
+ export type { ThemeModeProp } from "./types.js";
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/default/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,YAAY,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAC3E,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * `@stapel/vocabularies-react/default` — the pair's default AntD skin (§54: a pair ships a
3
+ * FEATURE, not only a bag). A separate entry point, so a host that brings its
4
+ * own visuals never pulls `antd` or the token bridge into its bundle;
5
+ * importing this subpath is the opt-in.
6
+ *
7
+ * ```tsx
8
+ * import { VocabularyTermSelect } from "@stapel/vocabularies-react/default";
9
+ * // under core's <I18nProvider>; the client is a prop, not a context read:
10
+ * <VocabularyTermSelect client={client} vocabulary="avito-phones" level="Vendor" … />
11
+ * ```
12
+ */
13
+ export { VocabularyTermSelect } from "./VocabularyTermSelect.js";
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/default/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The one prop every skin component in this package shares.
3
+ *
4
+ * `mode` is OPTIONAL and has no default here on purpose: the shared
5
+ * `SkinTheme` (`@stapel/tokens-antd/skin`) follows the host's theme when
6
+ * nobody overrides it, and a `mode = "light"` default in a pair is how a dark
7
+ * host ends up with one white rectangle in the middle of its app.
8
+ */
9
+ export interface ThemeModeProp {
10
+ readonly mode?: "light" | "dark";
11
+ }
12
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/default/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAClC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/default/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import type { FlowError } from "@stapel/core";
2
+ export type { FlowError } from "@stapel/core";
3
+ export { isErrorCode } from "@stapel/core";
4
+ /**
5
+ * Fold any thrown value into a {@link FlowError} using this pair's own
6
+ * module-scoped fallback key (`vocabularies.error.unknown`, an en string in
7
+ * {@link vocabulariesI18nBundleEn}) so a non-`StapelApiError` fault still renders
8
+ * real copy rather than a raw key. The primitive lives in `@stapel/core`
9
+ * (frontend-core-architecture §4b); this wrapper only pins the fallback.
10
+ */
11
+ export declare function toFlowError(error: unknown): FlowError;
12
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/flows/errors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAErD"}
@@ -0,0 +1,13 @@
1
+ import { toFlowError as coreToFlowError } from "@stapel/core";
2
+ export { isErrorCode } from "@stapel/core";
3
+ /**
4
+ * Fold any thrown value into a {@link FlowError} using this pair's own
5
+ * module-scoped fallback key (`vocabularies.error.unknown`, an en string in
6
+ * {@link vocabulariesI18nBundleEn}) so a non-`StapelApiError` fault still renders
7
+ * real copy rather than a raw key. The primitive lives in `@stapel/core`
8
+ * (frontend-core-architecture §4b); this wrapper only pins the fallback.
9
+ */
10
+ export function toFlowError(error) {
11
+ return coreToFlowError(error, "vocabularies.error.unknown");
12
+ }
13
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/flows/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,cAAc,CAAC;AAI9D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,eAAe,CAAC,KAAK,EAAE,4BAA4B,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Zero-flow registry shim (slim wave §21/S3). stapel-vocabularies annotates no
3
+ * `@flow_step` yet — its backend `docs/flows.json` carries no `vocabularies.*`
4
+ * flows, so `gen:flows` skips emission for this pair (no `flows/generated/`
5
+ * scaffolding). This hand-written shim preserves the pair's public
6
+ * flow-registry surface at its zero-flow shape.
7
+ *
8
+ * When the backend annotates flows, `pnpm gen:flows` emits
9
+ * `./generated/flows.gen.ts` again — replace these exports with re-exports
10
+ * from it (the shapes match by construction) and delete this file.
11
+ */
12
+ export declare const VOCABULARIES_FLOWS: {};
13
+ /** Canonical flow ids present in flows.json (none yet — see above). */
14
+ export type VocabulariesFlowId = keyof typeof VOCABULARIES_FLOWS;
15
+ export type VocabulariesFlowSpec = (typeof VOCABULARIES_FLOWS)[VocabulariesFlowId];
16
+ export interface FlowEndpoint {
17
+ readonly method: string;
18
+ readonly path: string;
19
+ }
20
+ /** All HTTP endpoints a flow touches, in step order (for the contract test / MSW). */
21
+ export declare function flowEndpoints(id: VocabulariesFlowId): readonly FlowEndpoint[];
22
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/flows/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,IAAc,CAAC;AAE9C,uEAAuE;AACvE,MAAM,MAAM,kBAAkB,GAAG,MAAM,OAAO,kBAAkB,CAAC;AAEjE,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,kBAAkB,CAAC,CAAC;AAEnF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,EAAE,EAAE,kBAAkB,GAAG,SAAS,YAAY,EAAE,CAO7E"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Zero-flow registry shim (slim wave §21/S3). stapel-vocabularies annotates no
3
+ * `@flow_step` yet — its backend `docs/flows.json` carries no `vocabularies.*`
4
+ * flows, so `gen:flows` skips emission for this pair (no `flows/generated/`
5
+ * scaffolding). This hand-written shim preserves the pair's public
6
+ * flow-registry surface at its zero-flow shape.
7
+ *
8
+ * When the backend annotates flows, `pnpm gen:flows` emits
9
+ * `./generated/flows.gen.ts` again — replace these exports with re-exports
10
+ * from it (the shapes match by construction) and delete this file.
11
+ */
12
+ export const VOCABULARIES_FLOWS = {};
13
+ /** All HTTP endpoints a flow touches, in step order (for the contract test / MSW). */
14
+ export function flowEndpoints(id) {
15
+ // Same widened body as the generated registry's — valid for the zero-flow
16
+ // shape AND correct once flows exist.
17
+ const spec = VOCABULARIES_FLOWS[id];
18
+ return spec ? spec.steps.flatMap((s) => s.endpoints) : [];
19
+ }
20
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/flows/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAW,CAAC;AAY9C,sFAAsF;AACtF,MAAM,UAAU,aAAa,CAAC,EAAsB;IAClD,0EAA0E;IAC1E,sCAAsC;IACtC,MAAM,IAAI,GAAG,kBAAkB,CAAC,EAAE,CAErB,CAAC;IACd,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { ReactElement, ReactNode } from "react";
2
+ import type { VocabulariesRuntime } from "../model/runtime.js";
3
+ /**
4
+ * Provides the wired {@link VocabulariesRuntime} to every vocabularies hook and
5
+ * headless component below it. Bring your own visual shell — this component
6
+ * renders nothing of its own. (Core's `createModuleContext` provider, bound
7
+ * to this pair — slim wave §21/S2.)
8
+ *
9
+ * ```tsx
10
+ * const runtime = createVocabulariesRuntime({ baseUrl: "/vocabularies/api/v1/" });
11
+ * // give runtime.client to core's <StapelConfigProvider config={{ client }}>
12
+ * <VocabulariesProvider runtime={runtime}>{app}</VocabulariesProvider>
13
+ * ```
14
+ */
15
+ export declare const VocabulariesProvider: (props: {
16
+ runtime: VocabulariesRuntime;
17
+ children: ReactNode;
18
+ }) => ReactElement;
19
+ //# sourceMappingURL=VocabulariesProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VocabulariesProvider.d.ts","sourceRoot":"","sources":["../../src/headless/VocabulariesProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAErD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,EAAE,CAAC,KAAK,EAAE;IACzC,OAAO,EAAE,mBAAmB,CAAC;IAC7B,QAAQ,EAAE,SAAS,CAAC;CACrB,KAAK,YAA6B,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { ModuleProvider } from "../model/context.js";
2
+ /**
3
+ * Provides the wired {@link VocabulariesRuntime} to every vocabularies hook and
4
+ * headless component below it. Bring your own visual shell — this component
5
+ * renders nothing of its own. (Core's `createModuleContext` provider, bound
6
+ * to this pair — slim wave §21/S2.)
7
+ *
8
+ * ```tsx
9
+ * const runtime = createVocabulariesRuntime({ baseUrl: "/vocabularies/api/v1/" });
10
+ * // give runtime.client to core's <StapelConfigProvider config={{ client }}>
11
+ * <VocabulariesProvider runtime={runtime}>{app}</VocabulariesProvider>
12
+ * ```
13
+ */
14
+ export const VocabulariesProvider = ModuleProvider;
15
+ //# sourceMappingURL=VocabulariesProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VocabulariesProvider.js","sourceRoot":"","sources":["../../src/headless/VocabulariesProvider.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAGZ,cAAc,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { Remediation } from "./generated/errors.gen.js";
2
+ export { VOCABULARIES_ERRORS, VOCABULARIES_ERROR_CODES, vocabulariesErrorBundleEn, } from "./generated/errors.gen.js";
3
+ export type { VocabulariesErrorCode, VocabulariesErrorSpec, Remediation, } from "./generated/errors.gen.js";
4
+ /**
5
+ * Resolve a backend error code to its remediation hint, or `undefined` for a
6
+ * code this module doesn't know (e.g. a cross-cutting `stapel.http.*` fallback).
7
+ * Zero guessing at runtime — a static lookup over the generated map.
8
+ */
9
+ export declare function explainVocabulariesError(code: string): Remediation | undefined;
10
+ //# sourceMappingURL=errorsMap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorsMap.d.ts","sourceRoot":"","sources":["../../src/i18n/errorsMap.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACV,qBAAqB,EACrB,qBAAqB,EACrB,WAAW,GACZ,MAAM,2BAA2B,CAAC;AAEnC;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAG9E"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The pair's error map (frontend-standard §4 checklist #7, frontend-core §2.5):
3
+ * the generated `code → { status, params, remediation, en }` catalog plus a
4
+ * tiny `explain()` lookup. Backs the manifest `errors` block and gives hosts a
5
+ * mechanical UX branch beside `t(code, params)`. The map itself is generated
6
+ * from the backend registry (`pnpm gen:errors`); this file only adds the lookup
7
+ * helper and re-exports the public surface.
8
+ */
9
+ import { VOCABULARIES_ERRORS } from "./generated/errors.gen.js";
10
+ export { VOCABULARIES_ERRORS, VOCABULARIES_ERROR_CODES, vocabulariesErrorBundleEn, } from "./generated/errors.gen.js";
11
+ /**
12
+ * Resolve a backend error code to its remediation hint, or `undefined` for a
13
+ * code this module doesn't know (e.g. a cross-cutting `stapel.http.*` fallback).
14
+ * Zero guessing at runtime — a static lookup over the generated map.
15
+ */
16
+ export function explainVocabulariesError(code) {
17
+ return VOCABULARIES_ERRORS[code]
18
+ ?.remediation;
19
+ }
20
+ //# sourceMappingURL=errorsMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorsMap.js","sourceRoot":"","sources":["../../src/i18n/errorsMap.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAGhE,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,2BAA2B,CAAC;AAOnC;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAY;IACnD,OAAQ,mBAAoE,CAAC,IAAI,CAAC;QAChF,EAAE,WAAW,CAAC;AAClB,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { I18nDictionary, I18nEngine } from "@stapel/core";
2
+ export { vocabulariesErrorBundleEs } from "./generated/errors.es.gen.js";
3
+ /**
4
+ * Spanish bundle for vocabularies-react — shipped as the
5
+ * `@stapel/vocabularies-react/i18n/es` subpath (i18n-shipping.md §2) so the locale is
6
+ * opt-in: a host that never registers it never carries these strings (the main
7
+ * entry does not import this module).
8
+ *
9
+ * TWO SOURCES, ON PURPOSE — see the ru bundle's header: the generated
10
+ * `vocabulariesErrorBundleEs` covers the codes stapel-core owns, and the 3
11
+ * stapel-vocabularies owns are authored below until upstream ships a
12
+ * `translations/errors.es.json`.
13
+ */
14
+ export declare const vocabulariesI18nBundleEs: I18nDictionary;
15
+ /**
16
+ * Register the Spanish bundle. The en bundle goes UNDER it
17
+ * (merge-priority convention): a key this locale has not translated yet
18
+ * degrades to ENGLISH, never to a raw key.
19
+ */
20
+ export declare function registerVocabulariesI18nEs(engine: I18nEngine, locale?: string): void;
21
+ //# sourceMappingURL=es.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"es.d.ts","sourceRoot":"","sources":["../../src/i18n/es.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI/D,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAEzE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,EAAE,cAkBtC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,UAAU,EAClB,MAAM,SAAO,GACZ,IAAI,CAGN"}