@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,58 @@
1
+ /**
2
+ * `ru` texts for the backend error codes this catalog carries.
3
+ *
4
+ * PARTIAL, and deliberately typed to say so: 3 key(s) owned by
5
+ * stapel_vocabularies are absent, because that owner ships no locale catalog
6
+ * (ERRORS_LOCALE_EXEMPT_OWNERS). English for them still comes from the registry
7
+ * artifact via the en bundle; the pair layers its own authored `ru`
8
+ * strings over this one until upstream ships translations. `Partial` is what
9
+ * makes the gap visible to TypeScript instead of a silent English fallback.
10
+ *
11
+ * Import from the pair's `./i18n/ru` subpath, NOT the main entry, so
12
+ * the locale stays out of hosts that don't ship it.
13
+ */
14
+ export const vocabulariesErrorBundleRu = {
15
+ "error.400.bad_request": "Некорректный запрос",
16
+ "error.400.captcha_invalid": "Проверка капчи не пройдена. Пожалуйста, попробуйте ещё раз.",
17
+ "error.400.captcha_required": "Требуется токен капчи.",
18
+ "error.400.expected_list": "Ожидался список элементов",
19
+ "error.400.field.blank": "Поле «{field}» не может быть пустым",
20
+ "error.400.field.does_not_exist": "«{field}» не существует",
21
+ "error.400.field.invalid": "Поле «{field}» содержит недопустимое значение",
22
+ "error.400.field.invalid_choice": "Недопустимый вариант для поля «{field}»",
23
+ "error.400.field.max_length": "Поле «{field}» должно содержать не более {max_length} символов",
24
+ "error.400.field.max_value": "Значение поля «{field}» должно быть не больше {max_value}",
25
+ "error.400.field.min_length": "Поле «{field}» должно содержать не менее {min_length} символов",
26
+ "error.400.field.min_value": "Значение поля «{field}» должно быть не меньше {min_value}",
27
+ "error.400.field.null": "Поле «{field}» не может быть null",
28
+ "error.400.field.required": "Поле «{field}» обязательно",
29
+ "error.400.field.unique": "Значение поля «{field}» должно быть уникальным",
30
+ "error.400.invalid_ad_id": "Недопустимый идентификатор объявления",
31
+ "error.400.validation_error": "Ошибка валидации",
32
+ "error.400.verification_failed": "Проверка не пройдена",
33
+ "error.400.verification_invalid_factor": "Этот способ подтверждения недоступен",
34
+ "error.401.unauthorized": "Требуется аутентификация",
35
+ "error.402.payment_required": "Требуется оплата",
36
+ "error.403.forbidden": "У вас нет прав для выполнения этого действия",
37
+ "error.403.network_blocked": "Запросы из этой сети не разрешены.",
38
+ "error.403.verification_enrollment_required": "Требуется регистрация фактора подтверждения.",
39
+ "error.403.verification_required": "Требуется дополнительная проверка",
40
+ "error.404.ad_not_found": "Объявление не найдено",
41
+ "error.404.not_found": "Запрошенный ресурс не найден",
42
+ "error.404.verification_challenge_not_found": "Запрос на подтверждение не найден или истёк",
43
+ "error.405.method_not_allowed": "Метод не разрешён",
44
+ "error.406.not_acceptable": "Недопустимый формат ответа",
45
+ "error.408.request_timeout": "Время ожидания запроса истекло",
46
+ "error.409.conflict": "Ресурс уже существует",
47
+ "error.410.gone": "Ресурс был безвозвратно удалён",
48
+ "error.413.payload_too_large": "Тело запроса слишком большое",
49
+ "error.415.unsupported_media_type": "Неподдерживаемый тип данных",
50
+ "error.422.unprocessable_entity": "Невозможно обработать данные запроса",
51
+ "error.423.locked": "Ресурс заблокирован",
52
+ "error.423.verification_locked": "Слишком много неудачных попыток — подтверждение заблокировано",
53
+ "error.429.rate_limit": "Слишком много попыток. Повторите попытку через {retry_after_minutes} мин.",
54
+ "error.429.too_many_requests": "Слишком много запросов. Пожалуйста, повторите попытку позже.",
55
+ "error.500.internal": "Что-то пошло не так",
56
+ "error.503.mandate_unavailable": "Не удалось проверить доступ к рабочему пространству",
57
+ };
58
+ //# sourceMappingURL=errors.ru.gen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.ru.gen.js","sourceRoot":"","sources":["../../../src/i18n/generated/errors.ru.gen.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAmD;IACvF,uBAAuB,EAAE,qBAAqB;IAC9C,2BAA2B,EAAE,6DAA6D;IAC1F,4BAA4B,EAAE,wBAAwB;IACtD,yBAAyB,EAAE,2BAA2B;IACtD,uBAAuB,EAAE,qCAAqC;IAC9D,gCAAgC,EAAE,yBAAyB;IAC3D,yBAAyB,EAAE,+CAA+C;IAC1E,gCAAgC,EAAE,yCAAyC;IAC3E,4BAA4B,EAAE,gEAAgE;IAC9F,2BAA2B,EAAE,2DAA2D;IACxF,4BAA4B,EAAE,gEAAgE;IAC9F,2BAA2B,EAAE,2DAA2D;IACxF,sBAAsB,EAAE,mCAAmC;IAC3D,0BAA0B,EAAE,4BAA4B;IACxD,wBAAwB,EAAE,gDAAgD;IAC1E,yBAAyB,EAAE,uCAAuC;IAClE,4BAA4B,EAAE,kBAAkB;IAChD,+BAA+B,EAAE,sBAAsB;IACvD,uCAAuC,EAAE,sCAAsC;IAC/E,wBAAwB,EAAE,0BAA0B;IACpD,4BAA4B,EAAE,kBAAkB;IAChD,qBAAqB,EAAE,8CAA8C;IACrE,2BAA2B,EAAE,oCAAoC;IACjE,4CAA4C,EAAE,8CAA8C;IAC5F,iCAAiC,EAAE,mCAAmC;IACtE,wBAAwB,EAAE,uBAAuB;IACjD,qBAAqB,EAAE,8BAA8B;IACrD,4CAA4C,EAAE,6CAA6C;IAC3F,8BAA8B,EAAE,mBAAmB;IACnD,0BAA0B,EAAE,4BAA4B;IACxD,2BAA2B,EAAE,gCAAgC;IAC7D,oBAAoB,EAAE,uBAAuB;IAC7C,gBAAgB,EAAE,gCAAgC;IAClD,6BAA6B,EAAE,8BAA8B;IAC7D,kCAAkC,EAAE,6BAA6B;IACjE,gCAAgC,EAAE,sCAAsC;IACxE,kBAAkB,EAAE,qBAAqB;IACzC,+BAA+B,EAAE,+DAA+D;IAChG,sBAAsB,EAAE,2EAA2E;IACnG,6BAA6B,EAAE,8DAA8D;IAC7F,oBAAoB,EAAE,qBAAqB;IAC3C,+BAA+B,EAAE,qDAAqD;CACvF,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { I18nDictionary, I18nEngine } from "@stapel/core";
2
+ /**
3
+ * vocabularies-react's own translation KEYS (frontend-standard §4.2): headless
4
+ * components never render literal strings — hosts resolve these via core's i18n
5
+ * engine (`useT`). Backend error codes flow through the SAME contour: a
6
+ * `StapelApiError.code` is already a key, so the default bundle below ships
7
+ * English fallbacks for both the backend error codes (generated) and the
8
+ * pair's own UI keys. Point core's `loadLocale` at stapel-translate to override
9
+ * per locale. UI keys live under the `vocabularies.` namespace.
10
+ */
11
+ export declare const VOCABULARIES_I18N_KEYS: {
12
+ readonly unknownError: "vocabularies.error.unknown";
13
+ readonly termSelectPlaceholder: "vocabularies.termSelect.placeholder";
14
+ readonly termSelectNoMatches: "vocabularies.termSelect.noMatches";
15
+ readonly termSelectUnavailableTitle: "vocabularies.termSelect.unavailable.title";
16
+ readonly termSelectUnavailable: "vocabularies.termSelect.unavailable";
17
+ };
18
+ export type VocabulariesI18nKey = (typeof VOCABULARIES_I18N_KEYS)[keyof typeof VOCABULARIES_I18N_KEYS];
19
+ /**
20
+ * English fallback bundle for vocabularies-react UI keys + backend error codes.
21
+ * The generated `vocabulariesErrorBundleEn` (from stapel-vocabularies's error registry,
22
+ * `pnpm gen:errors`) is spread FIRST so every backend `error.*` key has a
23
+ * fallback — a `StapelApiError.code` never renders as a raw key. Hand-polished
24
+ * copy below then OVERRIDES the generated English for the keys users see most.
25
+ */
26
+ export declare const vocabulariesI18nBundleEn: I18nDictionary;
27
+ /**
28
+ * Register vocabularies-react's key bundle into a core i18n engine (call once at
29
+ * startup). A later `loadLocale` from stapel-translate can layer localized
30
+ * overrides on top.
31
+ */
32
+ export declare function registerVocabulariesI18n(engine: I18nEngine, locale?: string): void;
33
+ //# sourceMappingURL=keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/i18n/keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/D;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB;;;;;;CAMzB,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAC7B,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,OAAO,sBAAsB,CAAC,CAAC;AAEvE;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,EAAE,cAatC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,SAAO,GAAG,IAAI,CAEhF"}
@@ -0,0 +1,44 @@
1
+ import { vocabulariesErrorBundleEn } from "./generated/errors.gen.js";
2
+ /**
3
+ * vocabularies-react's own translation KEYS (frontend-standard §4.2): headless
4
+ * components never render literal strings — hosts resolve these via core's i18n
5
+ * engine (`useT`). Backend error codes flow through the SAME contour: a
6
+ * `StapelApiError.code` is already a key, so the default bundle below ships
7
+ * English fallbacks for both the backend error codes (generated) and the
8
+ * pair's own UI keys. Point core's `loadLocale` at stapel-translate to override
9
+ * per locale. UI keys live under the `vocabularies.` namespace.
10
+ */
11
+ export const VOCABULARIES_I18N_KEYS = {
12
+ unknownError: "vocabularies.error.unknown",
13
+ termSelectPlaceholder: "vocabularies.termSelect.placeholder",
14
+ termSelectNoMatches: "vocabularies.termSelect.noMatches",
15
+ termSelectUnavailableTitle: "vocabularies.termSelect.unavailable.title",
16
+ termSelectUnavailable: "vocabularies.termSelect.unavailable",
17
+ };
18
+ /**
19
+ * English fallback bundle for vocabularies-react UI keys + backend error codes.
20
+ * The generated `vocabulariesErrorBundleEn` (from stapel-vocabularies's error registry,
21
+ * `pnpm gen:errors`) is spread FIRST so every backend `error.*` key has a
22
+ * fallback — a `StapelApiError.code` never renders as a raw key. Hand-polished
23
+ * copy below then OVERRIDES the generated English for the keys users see most.
24
+ */
25
+ export const vocabulariesI18nBundleEn = {
26
+ // Backend error codes — generated en fallbacks (coverage by construction).
27
+ ...vocabulariesErrorBundleEn,
28
+ // vocabularies-react UI
29
+ "vocabularies.error.unknown": "Something went wrong. Please try again.",
30
+ // the default skin's own copy (see i18n/ru.ts, i18n/es.ts)
31
+ "vocabularies.termSelect.placeholder": "Start typing to search…",
32
+ "vocabularies.termSelect.noMatches": "No term matches that.",
33
+ "vocabularies.termSelect.unavailable.title": "This list cannot be loaded",
34
+ "vocabularies.termSelect.unavailable": "The terms for this field come from a vocabulary service that is not configured here, so there is nothing to choose from. Nobody can answer this question until it is wired up — please report it.",
35
+ };
36
+ /**
37
+ * Register vocabularies-react's key bundle into a core i18n engine (call once at
38
+ * startup). A later `loadLocale` from stapel-translate can layer localized
39
+ * overrides on top.
40
+ */
41
+ export function registerVocabulariesI18n(engine, locale = "en") {
42
+ engine.registerBundle(locale, vocabulariesI18nBundleEn);
43
+ }
44
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/i18n/keys.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAEtE;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,YAAY,EAAE,4BAA4B;IAC1C,qBAAqB,EAAE,qCAAqC;IAC5D,mBAAmB,EAAE,mCAAmC;IACxD,0BAA0B,EAAE,2CAA2C;IACvE,qBAAqB,EAAE,qCAAqC;CACpD,CAAC;AAKX;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAmB;IACtD,2EAA2E;IAC3E,GAAG,yBAAyB;IAE5B,wBAAwB;IACxB,4BAA4B,EAAE,yCAAyC;IAEvE,2DAA2D;IAC3D,qCAAqC,EAAE,yBAAyB;IAChE,mCAAmC,EAAE,uBAAuB;IAC5D,2CAA2C,EAAE,4BAA4B;IACzE,qCAAqC,EACnC,mMAAmM;CACtM,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAkB,EAAE,MAAM,GAAG,IAAI;IACxE,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { I18nDictionary, I18nEngine } from "@stapel/core";
2
+ export { vocabulariesErrorBundleRu } from "./generated/errors.ru.gen.js";
3
+ /**
4
+ * Russian bundle for vocabularies-react — shipped as the
5
+ * `@stapel/vocabularies-react/i18n/ru` 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. The generated `vocabulariesErrorBundleRu` covers the
10
+ * 42 cross-cutting codes stapel-core owns and localizes. The 3 codes
11
+ * stapel-vocabularies owns are NOT in it and cannot be: the module ships no
12
+ * `translations/` directory at all, so the generator emits a `Partial` bundle
13
+ * and says so in its own header (`ERRORS_LOCALE_EXEMPT_OWNERS`, the
14
+ * stapel-geo / stapel-reviews precedent). They are authored below, beside the
15
+ * UI copy. When upstream ships `translations/errors.ru.json`, those three
16
+ * lines are deleted and the generated bundle covers them — the keys and the
17
+ * texts do not move.
18
+ */
19
+ export declare const vocabulariesI18nBundleRu: I18nDictionary;
20
+ /**
21
+ * Register the Russian bundle. The en bundle goes UNDER it
22
+ * (merge-priority convention): a key this locale has not translated yet
23
+ * degrades to ENGLISH, never to a raw key.
24
+ */
25
+ export declare function registerVocabulariesI18nRu(engine: I18nEngine, locale?: string): void;
26
+ //# sourceMappingURL=ru.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ru.d.ts","sourceRoot":"","sources":["../../src/i18n/ru.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI/D,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAEzE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,wBAAwB,EAAE,cAkBtC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,UAAU,EAClB,MAAM,SAAO,GACZ,IAAI,CAGN"}
@@ -0,0 +1,43 @@
1
+ import { vocabulariesErrorBundleRu } from "./generated/errors.ru.gen.js";
2
+ import { vocabulariesI18nBundleEn } from "./keys.js";
3
+ export { vocabulariesErrorBundleRu } from "./generated/errors.ru.gen.js";
4
+ /**
5
+ * Russian bundle for vocabularies-react — shipped as the
6
+ * `@stapel/vocabularies-react/i18n/ru` subpath (i18n-shipping.md §2) so the locale is
7
+ * opt-in: a host that never registers it never carries these strings (the main
8
+ * entry does not import this module).
9
+ *
10
+ * TWO SOURCES, ON PURPOSE. The generated `vocabulariesErrorBundleRu` covers the
11
+ * 42 cross-cutting codes stapel-core owns and localizes. The 3 codes
12
+ * stapel-vocabularies owns are NOT in it and cannot be: the module ships no
13
+ * `translations/` directory at all, so the generator emits a `Partial` bundle
14
+ * and says so in its own header (`ERRORS_LOCALE_EXEMPT_OWNERS`, the
15
+ * stapel-geo / stapel-reviews precedent). They are authored below, beside the
16
+ * UI copy. When upstream ships `translations/errors.ru.json`, those three
17
+ * lines are deleted and the generated bundle covers them — the keys and the
18
+ * texts do not move.
19
+ */
20
+ export const vocabulariesI18nBundleRu = {
21
+ // Backend error codes — generated ru texts for every key core owns.
22
+ ...vocabulariesErrorBundleRu,
23
+ // Backend error codes stapel-vocabularies owns — authored here (see above).
24
+ "error.400.vocabularies_bad_parent": "На родительском уровне «{level}» нет термина «{parent}»",
25
+ "error.404.vocabularies_level_not_found": "В справочнике «{vocabulary}» нет уровня «{level}»",
26
+ "error.404.vocabularies_vocabulary_not_found": "Справочник не найден",
27
+ // vocabularies-react UI
28
+ "vocabularies.error.unknown": "Что-то пошло не так. Попробуйте ещё раз.",
29
+ "vocabularies.termSelect.placeholder": "Начните вводить для поиска…",
30
+ "vocabularies.termSelect.noMatches": "Ничего не найдено.",
31
+ "vocabularies.termSelect.unavailable.title": "Список не удалось загрузить",
32
+ "vocabularies.termSelect.unavailable": "Значения для этого поля берутся из справочника, который здесь не подключён, и выбирать не из чего. Ответить на этот вопрос невозможно — сообщите, пожалуйста, об этом.",
33
+ };
34
+ /**
35
+ * Register the Russian bundle. The en bundle goes UNDER it
36
+ * (merge-priority convention): a key this locale has not translated yet
37
+ * degrades to ENGLISH, never to a raw key.
38
+ */
39
+ export function registerVocabulariesI18nRu(engine, locale = "ru") {
40
+ engine.registerBundle(locale, vocabulariesI18nBundleEn);
41
+ engine.registerBundle(locale, vocabulariesI18nBundleRu);
42
+ }
43
+ //# sourceMappingURL=ru.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ru.js","sourceRoot":"","sources":["../../src/i18n/ru.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAErD,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAEzE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAmB;IACtD,oEAAoE;IACpE,GAAG,yBAAyB;IAE5B,4EAA4E;IAC5E,mCAAmC,EACjC,yDAAyD;IAC3D,wCAAwC,EACtC,mDAAmD;IACrD,6CAA6C,EAAE,sBAAsB;IAErE,wBAAwB;IACxB,4BAA4B,EAAE,0CAA0C;IACxE,qCAAqC,EAAE,6BAA6B;IACpE,mCAAmC,EAAE,oBAAoB;IACzD,2CAA2C,EAAE,6BAA6B;IAC1E,qCAAqC,EACnC,wKAAwK;CAC3K,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAAkB,EAClB,MAAM,GAAG,IAAI;IAEb,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IACxD,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * `@stapel/vocabularies-react` — the headless React flow pair for stapel-vocabularies
3
+ * (frontend-standard §2). Business + state only, zero visual opinion. Built on
4
+ * `@stapel/core`'s StapelClient (verification-403 interception, token refresh,
5
+ * i18n, analytics, query layer).
6
+ *
7
+ * Scaffolded by `stapel-new-react-lib`. Layers: api → model → flows → headless
8
+ * → i18n. Generated surfaces (flows registry, error map, manifest, llms.txt)
9
+ * are produced by the monorepo `gen:*` drivers and stand under drift gates.
10
+ */
11
+ export { createVocabulariesApi } from "./api/vocabulariesApi.js";
12
+ export type { VocabulariesApi } from "./api/vocabulariesApi.js";
13
+ export type { Schemas, Vocabulary, Level, Term, TermPage } from "./api/types.js";
14
+ export { createVocabularyClient, DEFAULT_TERM_LIMIT, RESOLVE_BATCH, } from "./client.js";
15
+ export type { VocabularyClient, VocabularyTerm, CreateVocabularyClientOptions, } from "./client.js";
16
+ export { createFlowMachine, useFlow, isErrorCode } from "@stapel/core";
17
+ export type { FlowMachine, FlowMachineOptions, FlowStateBase, FlowError, } from "@stapel/core";
18
+ export { toFlowError } from "./flows/errors.js";
19
+ export { VOCABULARIES_FLOWS, flowEndpoints } from "./flows/registry.js";
20
+ export type { VocabulariesFlowId, VocabulariesFlowSpec, FlowEndpoint, } from "./flows/registry.js";
21
+ export { createVocabulariesRuntime } from "./model/runtime.js";
22
+ export type { VocabulariesRuntime, CreateVocabulariesRuntimeOptions, } from "./model/runtime.js";
23
+ export { VocabulariesRuntimeContext, useVocabulariesRuntime, useVocabulariesApi, useVocabulariesAnalytics, } from "./model/context.js";
24
+ export { vocabulariesQueryKeys } from "./model/queryKeys.js";
25
+ export { useTermSearch, TERM_SEARCH_DEBOUNCE_MS } from "./model/useTermSearch.js";
26
+ export type { TermSearchOptions, TermSearchState } from "./model/useTermSearch.js";
27
+ export { useTermLabels, termLabel } from "./model/useTermLabels.js";
28
+ export type { TermLabels, TermLabelsOptions } from "./model/useTermLabels.js";
29
+ export { VocabulariesProvider } from "./headless/VocabulariesProvider.js";
30
+ export { VOCABULARIES_I18N_KEYS, vocabulariesI18nBundleEn, registerVocabulariesI18n, } from "./i18n/keys.js";
31
+ export type { VocabulariesI18nKey } from "./i18n/keys.js";
32
+ export { VOCABULARIES_ERRORS, VOCABULARIES_ERROR_CODES, vocabulariesErrorBundleEn, explainVocabulariesError, } from "./i18n/errorsMap.js";
33
+ export type { VocabulariesErrorCode, VocabulariesErrorSpec, Remediation, } from "./i18n/errorsMap.js";
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,YAAY,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAQjF,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACvE,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,SAAS,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACxE,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,GACb,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EACV,mBAAmB,EACnB,gCAAgC,GACjC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAClF,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACpE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAG1E,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG1D,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,qBAAqB,EACrB,qBAAqB,EACrB,WAAW,GACZ,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `@stapel/vocabularies-react` — the headless React flow pair for stapel-vocabularies
3
+ * (frontend-standard §2). Business + state only, zero visual opinion. Built on
4
+ * `@stapel/core`'s StapelClient (verification-403 interception, token refresh,
5
+ * i18n, analytics, query layer).
6
+ *
7
+ * Scaffolded by `stapel-new-react-lib`. Layers: api → model → flows → headless
8
+ * → i18n. Generated surfaces (flows registry, error map, manifest, llms.txt)
9
+ * are produced by the monorepo `gen:*` drivers and stand under drift gates.
10
+ */
11
+ // ── api ──────────────────────────────────────────────────────────────────────
12
+ export { createVocabulariesApi } from "./api/vocabulariesApi.js";
13
+ // ── the seam (attributes-v2 §3.4) ────────────────────────────────────────────
14
+ // `createVocabularyClient` returns the two functions
15
+ // `@stapel/attributes-react` declares as `VocabularyClient` and hands to
16
+ // `<VocabularyClientProvider>`. The shape is satisfied STRUCTURALLY: neither
17
+ // package imports the other (test/clientShape.test.ts is the proof), so the
18
+ // two L2 pairs stay independently releasable.
19
+ export { createVocabularyClient, DEFAULT_TERM_LIMIT, RESOLVE_BATCH, } from "./client.js";
20
+ // ── flows ────────────────────────────────────────────────────────────────────
21
+ // The flow-machine primitive lives in `@stapel/core` (one reviewed copy for
22
+ // every pair — frontend-core-architecture §4b). Re-exported for ergonomics.
23
+ export { createFlowMachine, useFlow, isErrorCode } from "@stapel/core";
24
+ export { toFlowError } from "./flows/errors.js";
25
+ export { VOCABULARIES_FLOWS, flowEndpoints } from "./flows/registry.js";
26
+ // ── model (runtime wiring, query keys, context) ──────────────────────────────
27
+ export { createVocabulariesRuntime } from "./model/runtime.js";
28
+ export { VocabulariesRuntimeContext, useVocabulariesRuntime, useVocabulariesApi, useVocabulariesAnalytics, } from "./model/context.js";
29
+ export { vocabulariesQueryKeys } from "./model/queryKeys.js";
30
+ export { useTermSearch, TERM_SEARCH_DEBOUNCE_MS } from "./model/useTermSearch.js";
31
+ export { useTermLabels, termLabel } from "./model/useTermLabels.js";
32
+ // ── headless (renderless components) ─────────────────────────────────────────
33
+ export { VocabulariesProvider } from "./headless/VocabulariesProvider.js";
34
+ // ── i18n ─────────────────────────────────────────────────────────────────────
35
+ export { VOCABULARIES_I18N_KEYS, vocabulariesI18nBundleEn, registerVocabulariesI18n, } from "./i18n/keys.js";
36
+ // ── errors map (code → status/params/remediation/en; generated) ──────────────
37
+ export { VOCABULARIES_ERRORS, VOCABULARIES_ERROR_CODES, vocabulariesErrorBundleEn, explainVocabulariesError, } from "./i18n/errorsMap.js";
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,gFAAgF;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAIjE,gFAAgF;AAChF,qDAAqD;AACrD,yEAAyE;AACzE,6EAA6E;AAC7E,4EAA4E;AAC5E,8CAA8C;AAC9C,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,aAAa,GACd,MAAM,aAAa,CAAC;AAOrB,gFAAgF;AAChF,4EAA4E;AAC5E,4EAA4E;AAC5E,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAOvE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAOxE,gFAAgF;AAChF,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAK/D,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAElF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAGpE,gFAAgF;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAE1E,gFAAgF;AAChF,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AAGxB,gFAAgF;AAChF,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { Context } from "react";
2
+ import type { Analytics, ModuleContextKit } from "@stapel/core";
3
+ import type { VocabulariesApi } from "../api/vocabulariesApi.js";
4
+ import type { VocabulariesRuntime } from "./runtime.js";
5
+ export declare const VocabulariesRuntimeContext: Context<VocabulariesRuntime | null>;
6
+ export declare const useVocabulariesRuntime: () => VocabulariesRuntime;
7
+ export declare const useVocabulariesApi: () => VocabulariesApi;
8
+ export declare const useVocabulariesAnalytics: () => Analytics | null;
9
+ /** @internal Re-exported as `<VocabulariesProvider>` from `headless/`. */
10
+ export declare const ModuleProvider: ModuleContextKit<VocabulariesRuntime>["Provider"];
11
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/model/context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAErC,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAYxD,eAAO,MAAM,0BAA0B,EAAE,OAAO,CAAC,mBAAmB,GAAG,IAAI,CACvD,CAAC;AAErB,eAAO,MAAM,sBAAsB,EAAE,MAAM,mBAAoC,CAAC;AAEhF,eAAO,MAAM,kBAAkB,EAAE,MAAM,eAA4B,CAAC;AAEpE,eAAO,MAAM,wBAAwB,EAAE,MAAM,SAAS,GAAG,IAAuB,CAAC;AAEjF,0EAA0E;AAC1E,eAAO,MAAM,cAAc,EAAE,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,UAAU,CAC/D,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { createModuleContext } from "@stapel/core";
2
+ /**
3
+ * The wired VocabulariesRuntime shared through React context by
4
+ * `<VocabulariesProvider>`. Hooks in `model/` and `headless/` read the singletons
5
+ * from here. One reviewed copy of this plumbing lives in `@stapel/core`
6
+ * (`createModuleContext`, slim wave §21/S2); this module binds it under the
7
+ * pair's public names.
8
+ */
9
+ const kit = createModuleContext("Vocabularies");
10
+ export const VocabulariesRuntimeContext = kit.RuntimeContext;
11
+ export const useVocabulariesRuntime = kit.useRuntime;
12
+ export const useVocabulariesApi = kit.useApi;
13
+ export const useVocabulariesAnalytics = kit.useAnalytics;
14
+ /** @internal Re-exported as `<VocabulariesProvider>` from `headless/`. */
15
+ export const ModuleProvider = kit.Provider;
16
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/model/context.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAKnD;;;;;;GAMG;AACH,MAAM,GAAG,GACP,mBAAmB,CAAsB,cAAc,CAAC,CAAC;AAE3D,MAAM,CAAC,MAAM,0BAA0B,GACrC,GAAG,CAAC,cAAc,CAAC;AAErB,MAAM,CAAC,MAAM,sBAAsB,GAA8B,GAAG,CAAC,UAAU,CAAC;AAEhF,MAAM,CAAC,MAAM,kBAAkB,GAA0B,GAAG,CAAC,MAAM,CAAC;AAEpE,MAAM,CAAC,MAAM,wBAAwB,GAA2B,GAAG,CAAC,YAAY,CAAC;AAEjF,0EAA0E;AAC1E,MAAM,CAAC,MAAM,cAAc,GACzB,GAAG,CAAC,QAAQ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const vocabulariesQueryKeys: {
2
+ readonly all: readonly ["vocabularies"];
3
+ termLabels: (vocabulary: string, level: string, codes: readonly string[]) => readonly ["vocabularies", "termLabels", string, string, string];
4
+ };
5
+ //# sourceMappingURL=queryKeys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryKeys.d.ts","sourceRoot":"","sources":["../../src/model/queryKeys.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,qBAAqB,EAAE;IAClC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;IACxC,UAAU,EAAE,CACV,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,SAAS,MAAM,EAAE,KACrB,SAAS,CAAC,cAAc,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CAatE,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Namespaced TanStack Query keys (frontend-standard §2 — "keys are namespaced").
3
+ * Everything under the `"vocabularies"` root so a host can invalidate the whole
4
+ * module or match a single resource. Explicit tuple return types satisfy
5
+ * `--isolatedDeclarations`.
6
+ *
7
+ * Only ONE read is keyed here, and that is not an oversight: a term SEARCH is
8
+ * not a cacheable resource — it is superseded per keystroke and its answer is
9
+ * scoped to a dropdown that is about to close — so `useTermSearch` owns its own
10
+ * in-flight state and never enters the cache. `useTermLabels` is the opposite:
11
+ * a stable `{code: label}` for codes a page already holds, worth caching across
12
+ * every control that shows the same term, which is why it is a query.
13
+ */
14
+ const ROOT = "vocabularies";
15
+ export const vocabulariesQueryKeys = {
16
+ all: [ROOT],
17
+ // The codes are sorted and joined into ONE key segment: two controls asking
18
+ // for the same set in a different order are the same read, and an array
19
+ // segment would make them two cache entries and two round trips.
20
+ termLabels: (vocabulary, level, codes) => [
21
+ ROOT,
22
+ "termLabels",
23
+ vocabulary,
24
+ level,
25
+ [...codes].sort().join(","),
26
+ ],
27
+ };
28
+ //# sourceMappingURL=queryKeys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryKeys.js","sourceRoot":"","sources":["../../src/model/queryKeys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,IAAI,GAAG,cAAuB,CAAC;AAErC,MAAM,CAAC,MAAM,qBAAqB,GAO9B;IACF,GAAG,EAAE,CAAC,IAAI,CAAC;IACX,4EAA4E;IAC5E,wEAAwE;IACxE,iEAAiE;IACjE,UAAU,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;QACxC,IAAI;QACJ,YAAY;QACZ,UAAU;QACV,KAAK;QACL,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;KAC5B;CACF,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { CreateModuleRuntimeOptions, ModuleRuntime } from "@stapel/core";
2
+ import type { VocabulariesApi } from "../api/vocabulariesApi.js";
3
+ /**
4
+ * The wired vocabularies runtime — core's `ModuleRuntime` bound to this pair's
5
+ * API (slim wave §21/S2: the plumbing lives once in `@stapel/core`'s
6
+ * `createModuleRuntime`/`createModuleContext`; this module only binds the
7
+ * module-prefixed names). The returned `client` is what the host injects
8
+ * into core's `StapelConfigProvider` (as the default or the `"vocabularies"`
9
+ * module client), preserving the client-injection fork seam
10
+ * (frontend-standard §7.2). Auth token/refresh and the verification-403 seam
11
+ * are supplied by the host's auth runtime on the shared client — this pair
12
+ * does not re-implement them.
13
+ */
14
+ export type VocabulariesRuntime = ModuleRuntime<VocabulariesApi>;
15
+ export type CreateVocabulariesRuntimeOptions = CreateModuleRuntimeOptions;
16
+ export declare function createVocabulariesRuntime(options: CreateVocabulariesRuntimeOptions): VocabulariesRuntime;
17
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/model/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAEjE;;;;;;;;;;GAUG;AACH,MAAM,MAAM,mBAAmB,GAAG,aAAa,CAAC,eAAe,CAAC,CAAC;AAEjE,MAAM,MAAM,gCAAgC,GAAG,0BAA0B,CAAC;AAE1E,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,gCAAgC,GACxC,mBAAmB,CAErB"}
@@ -0,0 +1,6 @@
1
+ import { createModuleRuntime } from "@stapel/core";
2
+ import { createVocabulariesApi } from "../api/vocabulariesApi.js";
3
+ export function createVocabulariesRuntime(options) {
4
+ return createModuleRuntime(createVocabulariesApi, options);
5
+ }
6
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/model/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAkBlE,MAAM,UAAU,yBAAyB,CACvC,OAAyC;IAEzC,OAAO,mBAAmB,CAAC,qBAAqB,EAAE,OAAO,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { LoadState } from "@stapel/core";
2
+ import type { VocabularyClient } from "../client.js";
3
+ export interface TermLabelsOptions {
4
+ readonly vocabulary: string;
5
+ readonly level: string;
6
+ readonly codes: readonly string[];
7
+ }
8
+ export type TermLabels = Readonly<Record<string, string>>;
9
+ /**
10
+ * Labels for `codes`, as a load state. Disabled — and therefore `loading`,
11
+ * never `ready` with an empty map — while there is no client, no pointer or
12
+ * nothing to resolve.
13
+ */
14
+ export declare function useTermLabels(client: VocabularyClient | null, options: TermLabelsOptions): LoadState<TermLabels>;
15
+ /**
16
+ * The one right way to READ that state for display: a resolved label, or the
17
+ * code itself while the answer is in flight, when the load failed, or when the
18
+ * server omitted the code because it does not know it.
19
+ *
20
+ * All four fall back the same way ON PURPOSE — the code is what the person's
21
+ * answer literally is, so showing it is never wrong, only less kind. A control
22
+ * that needs to distinguish them (an admin screen auditing dead codes) reads
23
+ * the {@link LoadState} directly.
24
+ */
25
+ export declare function termLabel(labels: LoadState<TermLabels>, code: string): string;
26
+ //# sourceMappingURL=useTermLabels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTermLabels.d.ts","sourceRoot":"","sources":["../../src/model/useTermLabels.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGrD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE1D;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,gBAAgB,GAAG,IAAI,EAC/B,OAAO,EAAE,iBAAiB,GACzB,SAAS,CAAC,UAAU,CAAC,CAevB;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7E"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * `useTermLabels` — `{code: label}` for codes a page already HOLDS.
3
+ *
4
+ * The other half of the seam. A stored answer on a listing is a list of term
5
+ * CODES (`["apple", "iphone-15-pro"]`); the labels are not stored with it,
6
+ * because a label is translated and a code is not. So a reopened draft, a
7
+ * filter chip, a facet row — anything showing an answer somebody already gave
8
+ * — has to ask for the words.
9
+ *
10
+ * Unlike a search this IS a cacheable resource: the same codes give the same
11
+ * labels until the vocabulary's revision moves, and several controls on one
12
+ * page routinely ask for the same set. So it is a TanStack query keyed through
13
+ * the factory, and the answer is a {@link LoadState} rather than a bare map —
14
+ * `{}` would say "these codes have no labels" in exactly the same words as
15
+ * "nobody has asked yet" and "the request failed" (core `loadState.ts`).
16
+ *
17
+ * The fallback a caller wants is almost always the CODE ITSELF, which is what
18
+ * {@link termLabel} does: the stored answer is the truth, and a blank control
19
+ * is a worse lie than a slug.
20
+ */
21
+ import { useQuery } from "@tanstack/react-query";
22
+ import { loadStateFromQuery } from "@stapel/core";
23
+ import { vocabulariesQueryKeys } from "./queryKeys.js";
24
+ /**
25
+ * Labels for `codes`, as a load state. Disabled — and therefore `loading`,
26
+ * never `ready` with an empty map — while there is no client, no pointer or
27
+ * nothing to resolve.
28
+ */
29
+ export function useTermLabels(client, options) {
30
+ const { vocabulary, level, codes } = options;
31
+ const wanted = codes.filter((code) => code.length > 0);
32
+ const enabled = client !== null && vocabulary.length > 0 && level.length > 0 && wanted.length > 0;
33
+ const query = useQuery({
34
+ queryKey: vocabulariesQueryKeys.termLabels(vocabulary, level, wanted),
35
+ enabled,
36
+ queryFn: async () => {
37
+ // `enabled` already guarantees this, and the compiler does not know it.
38
+ if (client === null)
39
+ return {};
40
+ return await client.resolve(vocabulary, level, wanted);
41
+ },
42
+ });
43
+ return loadStateFromQuery(query);
44
+ }
45
+ /**
46
+ * The one right way to READ that state for display: a resolved label, or the
47
+ * code itself while the answer is in flight, when the load failed, or when the
48
+ * server omitted the code because it does not know it.
49
+ *
50
+ * All four fall back the same way ON PURPOSE — the code is what the person's
51
+ * answer literally is, so showing it is never wrong, only less kind. A control
52
+ * that needs to distinguish them (an admin screen auditing dead codes) reads
53
+ * the {@link LoadState} directly.
54
+ */
55
+ export function termLabel(labels, code) {
56
+ return labels.status === "ready" ? (labels.data[code] ?? code) : code;
57
+ }
58
+ //# sourceMappingURL=useTermLabels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTermLabels.js","sourceRoot":"","sources":["../../src/model/useTermLabels.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGlD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAUvD;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,MAA+B,EAC/B,OAA0B;IAE1B,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAC7C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvD,MAAM,OAAO,GACX,MAAM,KAAK,IAAI,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACpF,MAAM,KAAK,GAAG,QAAQ,CAAC;QACrB,QAAQ,EAAE,qBAAqB,CAAC,UAAU,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC;QACrE,OAAO;QACP,OAAO,EAAE,KAAK,IAAyB,EAAE;YACvC,wEAAwE;YACxE,IAAI,MAAM,KAAK,IAAI;gBAAE,OAAO,EAAE,CAAC;YAC/B,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACzD,CAAC;KACF,CAAC,CAAC;IACH,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS,CAAC,MAA6B,EAAE,IAAY;IACnE,OAAO,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACxE,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { VocabularyClient, VocabularyTerm } from "../client.js";
2
+ /** The pause after the last keystroke before a query goes to the server. Long
3
+ * enough that typing a word is one request, short enough that it still feels
4
+ * like the control answered. Mirrors the ref editors in attributes-react. */
5
+ export declare const TERM_SEARCH_DEBOUNCE_MS = 250;
6
+ export interface TermSearchOptions {
7
+ readonly vocabulary: string;
8
+ readonly level: string;
9
+ /** Code of a term at the level above; narrows the page to its children.
10
+ * `undefined` means the whole level. */
11
+ readonly parent?: string | undefined;
12
+ readonly debounceMs?: number;
13
+ }
14
+ export interface TermSearchState {
15
+ readonly terms: readonly VocabularyTerm[];
16
+ readonly loading: boolean;
17
+ /** A person typed. Debounced and superseding. */
18
+ search: (query: string) => void;
19
+ /** A dropdown opened. Fetches the first page immediately, once per
20
+ * (vocabulary, level, parent). */
21
+ open: () => void;
22
+ }
23
+ export declare function useTermSearch(client: VocabularyClient | null, options: TermSearchOptions): TermSearchState;
24
+ //# sourceMappingURL=useTermSearch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTermSearch.d.ts","sourceRoot":"","sources":["../../src/model/useTermSearch.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAErE;;6EAE6E;AAC7E,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAE3C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;4CACwC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,iDAAiD;IACjD,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC;sCACkC;IAClC,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,gBAAgB,GAAG,IAAI,EAC/B,OAAO,EAAE,iBAAiB,GACzB,eAAe,CA8DjB"}