@texaryn/react 0.4.4 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,59 @@
1
1
  # @texaryn/react
2
2
 
3
+ ## 0.5.1
4
+
5
+ ### Patch Changes
6
+
7
+ - d3ea7a8: `homepage` points at the documentation site, https://texaryn.github.io/texaryn/,
8
+ instead of the GitHub README. No code changes.
9
+ - Updated dependencies [d3ea7a8]
10
+ - Updated dependencies [d3ea7a8]
11
+ - @texaryn/core@0.12.1
12
+
13
+ ## 0.5.0
14
+
15
+ ### Minor Changes
16
+
17
+ - 191787c: `FormProvider` takes `messages`, a whole `FormMessages` set, and every built-in
18
+ widget renders from it. `useFormMessages()` is how a custom widget reads it.
19
+
20
+ Removed: `removeActionName`, `moveUpActionName`, `addActionName` and
21
+ `REQUIRED_INDICATOR`. Their purpose was letting a custom widget match the
22
+ built-in wording, and a function that returns English whatever is configured
23
+ now serves that purpose wrongly, leaving one widget in English while the form
24
+ translates. Migration:
25
+
26
+ before
27
+
28
+ removeActionName(position, itemTitle, arrayTitle)
29
+ <span aria-hidden="true"> {REQUIRED_INDICATOR}</span>
30
+
31
+ after
32
+
33
+ const messages = useFormMessages()
34
+ messages.removeItem({ position, itemTitle, containerTitle: arrayTitle }).accessibleName
35
+ messages.requiredIndicator() // { text, placement }
36
+
37
+ `ArrayActions`'s `addName` and `removeName(position, item)` are replaced by
38
+ `add` and `remove(position, item)`, each returning an `ActionMessage` carrying
39
+ `label` and `accessibleName` together.
40
+ - aa5dd6f: `ErrorSummary` is a named group with an `h2` heading and takes focus once a
41
+ failed submit settles, once per attempt; a successful submit, a validation
42
+ exception and blur or change validation move nothing. `focus={false}` keeps
43
+ it passive, for an application that renders one runtime twice and wants one
44
+ focusing summary. The heading and the text after each link come from
45
+ `errorSummaryHeading` and `errorSummaryDetail` in `FormMessages`.
46
+
47
+ ### Patch Changes
48
+
49
+ - 3f19d2c: `ErrorSummary` reads its label and message fallbacks from
50
+ `visibleErrorLabel` and `visibleErrorMessages` in `@texaryn/core`. Rendered
51
+ output is unchanged.
52
+ - Updated dependencies [191787c]
53
+ - Updated dependencies [aa5dd6f]
54
+ - Updated dependencies [3f19d2c]
55
+ - @texaryn/core@0.12.0
56
+
3
57
  ## 0.4.4
4
58
 
5
59
  ### Patch Changes
package/README.md CHANGED
@@ -100,6 +100,10 @@ namespace for that rendering surface:
100
100
  </FormProvider>
101
101
  ```
102
102
 
103
+ `messages` takes a whole `FormMessages` set from `@texaryn/core` and replaces
104
+ every word the built-in widgets invent. See the localizing guide on the docs
105
+ site. Custom widgets read it with `useFormMessages()`.
106
+
103
107
  `useFormContext()` returns the current runtime and `useFormIdPrefix()` returns
104
108
  the namespace. Rendering through `FormContext.Provider` instead throws: the
105
109
  context alone carries no namespace, which is what let two forms on one page
@@ -153,7 +157,7 @@ import { FieldErrors } from '@texaryn/react'
153
157
  <FieldErrors node={node} errors={errors} showErrors={showErrors} />
154
158
  ```
155
159
 
156
- `ErrorSummary` reads the runtime's `visibleErrors` store and renders a jump-linked list of every currently visible error above the form:
160
+ `ErrorSummary` renders a named group, headed by an `h2`, listing every visible error with a link to its field, and takes focus once a failed submit settles, once per attempt. Pass `focus={false}` on all but one summary when one runtime is rendered twice. The heading and the text after each link come from `errorSummaryHeading` and `errorSummaryDetail` in `FormMessages`.
157
161
 
158
162
  ```tsx
159
163
  import { ErrorSummary } from '@texaryn/react'
@@ -270,15 +274,13 @@ The schema adapter interprets data semantics. The core compiles and runs the for
270
274
  - `useObjectGroup`
271
275
  - `useArrayActions`
272
276
  - `ArrayActions`
273
- - `removeActionName`
274
- - `moveUpActionName`
275
- - `addActionName`
276
277
  - `ObjectGroup`
277
278
  - `FieldBinding`
278
279
  - `DomValueInputProps`
279
280
  - `DomCheckedInputProps`
280
281
  - `DomInputBaseProps`
281
282
  - `useFormContext`
283
+ - `useFormMessages`
282
284
 
283
285
  ### Context and rendering
284
286
 
@@ -299,7 +301,6 @@ The schema adapter interprets data semantics. The core compiles and runs the for
299
301
  - `FieldErrors`
300
302
  - `FieldLabelContent`
301
303
  - `FieldLabelContentProps`
302
- - `REQUIRED_INDICATOR`
303
304
  - `FieldErrorsProps`
304
305
  - `ErrorSummary`
305
306
 
@@ -1,8 +1,7 @@
1
- /**
2
- * Deliberately not a live region. The fields already announce their own
3
- * errors, so an aggregate one would speak the same validation event twice.
4
- * What this needs instead is to become a focus destination after a failed
5
- * submit, which is separate work.
6
- */
7
- export declare function ErrorSummary(): import("react").JSX.Element | null;
1
+ export interface ErrorSummaryProps {
2
+ /** Off for all but one summary when one runtime is rendered twice. */
3
+ focus?: boolean;
4
+ }
5
+ /** Not a live region: the fields announce their own errors, so the focus move after a failed submit is what speaks the heading. */
6
+ export declare function ErrorSummary({ focus }: ErrorSummaryProps): import("react").JSX.Element | null;
8
7
  //# sourceMappingURL=ErrorSummary.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorSummary.d.ts","sourceRoot":"","sources":["../../src/components/ErrorSummary.tsx"],"names":[],"mappings":"AAMA;;;;;GAKG;AACH,wBAAgB,YAAY,uCAwB3B"}
1
+ {"version":3,"file":"ErrorSummary.d.ts","sourceRoot":"","sources":["../../src/components/ErrorSummary.tsx"],"names":[],"mappings":"AASA,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,mIAAmI;AACnI,wBAAgB,YAAY,CAAC,EAAE,KAAY,EAAE,EAAE,iBAAiB,sCAiC/D"}
@@ -1,21 +1,31 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from 'react';
3
+ import { createFailedSubmitTracker, visibleErrorLabel, visibleErrorMessages } from '@texaryn/core';
2
4
  import { useFormContext } from '../context.js';
3
5
  import { useStore } from '../hooks/use-store.js';
4
6
  import { useFormIdPrefix } from '../id-prefix.js';
7
+ import { useFormMessages } from '../messages.js';
5
8
  import { makeId } from '../props/field-props.js';
6
- /**
7
- * Deliberately not a live region. The fields already announce their own
8
- * errors, so an aggregate one would speak the same validation event twice.
9
- * What this needs instead is to become a focus destination after a failed
10
- * submit, which is separate work.
11
- */
12
- export function ErrorSummary() {
9
+ /** Not a live region: the fields announce their own errors, so the focus move after a failed submit is what speaks the heading. */
10
+ export function ErrorSummary({ focus = true }) {
13
11
  const runtime = useFormContext();
14
12
  const idPrefix = useFormIdPrefix();
13
+ const messages = useFormMessages();
15
14
  const visibleErrors = useStore(runtime.visibleErrors);
15
+ const submission = useStore(runtime.submission);
16
+ const container = useRef(null);
17
+ const tracker = useRef(null);
18
+ tracker.current ??= createFailedSubmitTracker(submission);
19
+ useEffect(() => {
20
+ if (!tracker.current.settle(submission, visibleErrors))
21
+ return;
22
+ if (focus && container.current?.isConnected)
23
+ container.current.focus();
24
+ }, [submission, visibleErrors, focus]);
16
25
  if (visibleErrors.length === 0) {
17
26
  return null;
18
27
  }
19
- return (_jsx("div", { children: _jsx("ul", { children: visibleErrors.map((entry) => (_jsxs("li", { children: [_jsx("a", { href: `#${makeId(idPrefix, entry.nodeId, 'input')}`, children: entry.fieldTitle ?? entry.pointer ?? entry.nodeId }), ': ', entry.errors.map((error) => error.message ?? error.keyword).join(', ')] }, entry.nodeId))) }) }));
28
+ const headingId = makeId(idPrefix, 'error-summary', 'heading');
29
+ return (_jsxs("div", { role: "group", tabIndex: -1, "aria-labelledby": headingId, ref: container, children: [_jsx("h2", { id: headingId, children: messages.errorSummaryHeading({ count: visibleErrors.length }) }), _jsx("ul", { children: visibleErrors.map((entry) => (_jsxs("li", { children: [_jsx("a", { href: `#${makeId(idPrefix, entry.nodeId, 'input')}`, children: visibleErrorLabel(entry) }), messages.errorSummaryDetail({ messages: visibleErrorMessages(entry) })] }, entry.nodeId))) })] }));
20
30
  }
21
31
  //# sourceMappingURL=ErrorSummary.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorSummary.js","sourceRoot":"","sources":["../../src/components/ErrorSummary.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAEhD;;;;;GAKG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,OAAO,GAAG,cAAc,EAAE,CAAA;IAChC,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAA;IAClC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA;IAErD,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,CACL,wBACE,uBACG,aAAa,CAAC,GAAG,CAAC,CAAC,KAAmB,EAAE,EAAE,CAAC,CAC1C,yBACE,YAAG,IAAI,EAAE,IAAI,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YACnD,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,GAChD,EACH,IAAI,EACJ,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KALhE,KAAK,CAAC,MAAM,CAMhB,CACN,CAAC,GACC,GACD,CACP,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"ErrorSummary.js","sourceRoot":"","sources":["../../src/components/ErrorSummary.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AACzC,OAAO,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAElG,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAOhD,mIAAmI;AACnI,MAAM,UAAU,YAAY,CAAC,EAAE,KAAK,GAAG,IAAI,EAAqB;IAC9D,MAAM,OAAO,GAAG,cAAc,EAAE,CAAA;IAChC,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAA;IAClC,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAA;IAClC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA;IACrD,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IAC/C,MAAM,SAAS,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IAC9C,MAAM,OAAO,GAAG,MAAM,CAA6B,IAAI,CAAC,CAAA;IACxD,OAAO,CAAC,OAAO,KAAK,yBAAyB,CAAC,UAAU,CAAC,CAAA;IAEzD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO,CAAC,OAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC;YAAE,OAAM;QAC/D,IAAI,KAAK,IAAI,SAAS,CAAC,OAAO,EAAE,WAAW;YAAE,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;IACxE,CAAC,EAAE,CAAC,UAAU,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC,CAAA;IAEtC,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,EAAE,eAAe,EAAE,SAAS,CAAC,CAAA;IAC9D,OAAO,CACL,eAAK,IAAI,EAAC,OAAO,EAAC,QAAQ,EAAE,CAAC,CAAC,qBAAmB,SAAS,EAAE,GAAG,EAAE,SAAS,aACxE,aAAI,EAAE,EAAE,SAAS,YAAG,QAAQ,CAAC,mBAAmB,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,GAAM,EACvF,uBACG,aAAa,CAAC,GAAG,CAAC,CAAC,KAAmB,EAAE,EAAE,CAAC,CAC1C,yBACE,YAAG,IAAI,EAAE,IAAI,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAG,iBAAiB,CAAC,KAAK,CAAC,GAAK,EACrF,QAAQ,CAAC,kBAAkB,CAAC,EAAE,QAAQ,EAAE,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC,KAFhE,KAAK,CAAC,MAAM,CAGhB,CACN,CAAC,GACC,IACD,CACP,CAAA;AACH,CAAC"}
@@ -1,6 +1,4 @@
1
1
  import React from 'react';
2
- /** The wording every binding uses, so a custom widget can match it. */
3
- export declare const REQUIRED_INDICATOR = "(required)";
4
2
  export interface FieldLabelContentProps {
5
3
  label: string;
6
4
  required: boolean;
@@ -10,11 +8,11 @@ export interface FieldLabelContentProps {
10
8
  * indicator that is kept out of the accessible name.
11
9
  *
12
10
  * Three separate channels carry one fact, and they must not be collapsed. The
13
- * sighted user reads "(required)". The accessible name stays the label alone,
11
+ * sighted user reads the indicator. The accessible name stays the label alone,
14
12
  * because `aria-required` already reports the state and putting it in the name
15
- * as well makes some screen readers say it twice. The indicator says the word
16
- * rather than an asterisk, so nobody has to be told elsewhere what a marker
17
- * means.
13
+ * as well makes some screen readers say it twice. The message decides the
14
+ * wording and which side of the label it sits on; this component decides that
15
+ * it is `aria-hidden`.
18
16
  *
19
17
  * Shared by the three React widget sets so they cannot drift on it.
20
18
  */
@@ -1 +1 @@
1
- {"version":3,"file":"FieldLabelContent.d.ts","sourceRoot":"","sources":["../../src/components/FieldLabelContent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,uEAAuE;AACvE,eAAO,MAAM,kBAAkB,eAAe,CAAA;AAE9C,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,sBAAsB,qBAO5E"}
1
+ {"version":3,"file":"FieldLabelContent.d.ts","sourceRoot":"","sources":["../../src/components/FieldLabelContent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,sBAAsB,qBAoB5E"}
@@ -1,21 +1,25 @@
1
- import { jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from 'react';
3
- /** The wording every binding uses, so a custom widget can match it. */
4
- export const REQUIRED_INDICATOR = '(required)';
3
+ import { useFormMessages } from '../messages.js';
5
4
  /**
6
5
  * Label content for a field: the schema's label, plus a visible required
7
6
  * indicator that is kept out of the accessible name.
8
7
  *
9
8
  * Three separate channels carry one fact, and they must not be collapsed. The
10
- * sighted user reads "(required)". The accessible name stays the label alone,
9
+ * sighted user reads the indicator. The accessible name stays the label alone,
11
10
  * because `aria-required` already reports the state and putting it in the name
12
- * as well makes some screen readers say it twice. The indicator says the word
13
- * rather than an asterisk, so nobody has to be told elsewhere what a marker
14
- * means.
11
+ * as well makes some screen readers say it twice. The message decides the
12
+ * wording and which side of the label it sits on; this component decides that
13
+ * it is `aria-hidden`.
15
14
  *
16
15
  * Shared by the three React widget sets so they cannot drift on it.
17
16
  */
18
17
  export function FieldLabelContent({ label, required }) {
19
- return (_jsxs(_Fragment, { children: [label, required ? _jsxs("span", { "aria-hidden": "true", children: [" ", REQUIRED_INDICATOR] }) : null] }));
18
+ const messages = useFormMessages();
19
+ if (!required)
20
+ return _jsx(_Fragment, { children: label });
21
+ const indicator = messages.requiredIndicator();
22
+ const marker = (_jsx("span", { "aria-hidden": "true", children: indicator.placement === 'after' ? ` ${indicator.text}` : `${indicator.text} ` }));
23
+ return indicator.placement === 'after' ? (_jsxs(_Fragment, { children: [label, marker] })) : (_jsxs(_Fragment, { children: [marker, label] }));
20
24
  }
21
25
  //# sourceMappingURL=FieldLabelContent.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FieldLabelContent.js","sourceRoot":"","sources":["../../src/components/FieldLabelContent.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,uEAAuE;AACvE,MAAM,CAAC,MAAM,kBAAkB,GAAG,YAAY,CAAA;AAO9C;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAA0B;IAC3E,OAAO,CACL,8BACG,KAAK,EACL,QAAQ,CAAC,CAAC,CAAC,+BAAkB,MAAM,kBAAG,kBAAkB,IAAQ,CAAC,CAAC,CAAC,IAAI,IACvE,CACJ,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"FieldLabelContent.js","sourceRoot":"","sources":["../../src/components/FieldLabelContent.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAOhD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAA0B;IAC3E,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAA;IAClC,IAAI,CAAC,QAAQ;QAAE,OAAO,4BAAG,KAAK,GAAI,CAAA;IAClC,MAAM,SAAS,GAAG,QAAQ,CAAC,iBAAiB,EAAE,CAAA;IAC9C,MAAM,MAAM,GAAG,CACb,8BAAkB,MAAM,YACrB,SAAS,CAAC,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,IAAI,GAAG,GACzE,CACR,CAAA;IACD,OAAO,SAAS,CAAC,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,CACvC,8BACG,KAAK,EACL,MAAM,IACN,CACJ,CAAC,CAAC,CAAC,CACF,8BACG,MAAM,EACN,KAAK,IACL,CACJ,CAAA;AACH,CAAC"}
package/dist/context.d.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  import type { ReactNode } from 'react';
2
- import type { FormRuntime } from '@texaryn/core';
2
+ import type { FormMessages, FormRuntime } from '@texaryn/core';
3
3
  export declare const FormContext: import("react").Context<FormRuntime | null>;
4
4
  export interface FormProviderProps {
5
5
  value: FormRuntime | null;
6
+ /** The whole set, or English. Passed through by identity, so a stable object costs no re-render. */
7
+ messages?: FormMessages;
6
8
  children?: ReactNode;
7
9
  }
8
10
  /**
@@ -14,6 +16,6 @@ export interface FormProviderProps {
14
16
  * siblings of FormRoot, ErrorSummary in particular, resolve the same namespace
15
17
  * the fields do.
16
18
  */
17
- export declare function FormProvider({ value, children }: FormProviderProps): import("react").JSX.Element;
19
+ export declare function FormProvider({ value, messages, children }: FormProviderProps): import("react").JSX.Element;
18
20
  export declare function useFormContext(): FormRuntime;
19
21
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAGhD,eAAO,MAAM,WAAW,6CAA0C,CAAA;AAElE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IACzB,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,iBAAiB,+BAOlE;AAED,wBAAgB,cAAc,IAAI,WAAW,CAM5C"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAI9D,eAAO,MAAM,WAAW,6CAA0C,CAAA;AAElE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IACzB,oGAAoG;IACpG,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,iBAAiB,+BAS5E;AAED,wBAAgB,cAAc,IAAI,WAAW,CAM5C"}
package/dist/context.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { createContext, useContext } from 'react';
3
+ import { englishMessages } from '@texaryn/core';
3
4
  import { IdPrefixProvider, useGeneratedIdPrefix } from './id-prefix.js';
5
+ import { MessagesProvider } from './messages.js';
4
6
  export const FormContext = createContext(null);
5
7
  /**
6
8
  * The rendering surface, and therefore the DOM namespace, for one form.
@@ -11,9 +13,9 @@ export const FormContext = createContext(null);
11
13
  * siblings of FormRoot, ErrorSummary in particular, resolve the same namespace
12
14
  * the fields do.
13
15
  */
14
- export function FormProvider({ value, children }) {
16
+ export function FormProvider({ value, messages, children }) {
15
17
  const idPrefix = useGeneratedIdPrefix();
16
- return (_jsx(FormContext.Provider, { value: value, children: _jsx(IdPrefixProvider, { value: idPrefix, children: children }) }));
18
+ return (_jsx(FormContext.Provider, { value: value, children: _jsx(IdPrefixProvider, { value: idPrefix, children: _jsx(MessagesProvider, { value: messages ?? englishMessages, children: children }) }) }));
17
19
  }
18
20
  export function useFormContext() {
19
21
  const runtime = useContext(FormContext);
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAGjD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAEvE,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAqB,IAAI,CAAC,CAAA;AAOlE;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAqB;IACjE,MAAM,QAAQ,GAAG,oBAAoB,EAAE,CAAA;IACvC,OAAO,CACL,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAChC,KAAC,gBAAgB,IAAC,KAAK,EAAE,QAAQ,YAAG,QAAQ,GAAoB,GAC3C,CACxB,CAAA;AACH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,CAAC,CAAA;IACvC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;IACtE,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAEjD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE/C,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEhD,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAqB,IAAI,CAAC,CAAA;AASlE;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAqB;IAC3E,MAAM,QAAQ,GAAG,oBAAoB,EAAE,CAAA;IACvC,OAAO,CACL,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAChC,KAAC,gBAAgB,IAAC,KAAK,EAAE,QAAQ,YAC/B,KAAC,gBAAgB,IAAC,KAAK,EAAE,QAAQ,IAAI,eAAe,YAAG,QAAQ,GAAoB,GAClE,GACE,CACxB,CAAA;AACH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,CAAC,CAAA;IACvC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;IACtE,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -1,9 +1,9 @@
1
- import type { UINode } from '@texaryn/core';
1
+ import type { ActionMessage, UINode } from '@texaryn/core';
2
2
  export interface ArrayActions {
3
- /** Accessible name for the control that removes the row at this position. */
4
- removeName(position: number, item: UINode | undefined): string;
5
- /** Accessible name for the control that appends a row. */
6
- addName: string;
3
+ /** Both surfaces of the control that appends a row. */
4
+ add: ActionMessage;
5
+ /** Both surfaces of the control that removes the row at this position. */
6
+ remove(position: number, item: UINode | undefined): ActionMessage;
7
7
  }
8
8
  /**
9
9
  * Shared by the three React widget sets so their action names cannot drift.
@@ -1 +1 @@
1
- {"version":3,"file":"use-array-actions.d.ts","sourceRoot":"","sources":["../../src/hooks/use-array-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,MAAM,EAAE,MAAM,eAAe,CAAA;AAI1D,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;IAC9D,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAW1D"}
1
+ {"version":3,"file":"use-array-actions.d.ts","sourceRoot":"","sources":["../../src/hooks/use-array-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,EAAE,MAAM,eAAe,CAAA;AAIzE,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,GAAG,EAAE,aAAa,CAAA;IAClB,0EAA0E;IAC1E,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,CAAA;CAClE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAa1D"}
@@ -1,5 +1,5 @@
1
1
  import { useRendererContext } from '../components/renderer-context.js';
2
- import { addActionName, removeActionName } from '../props/action-names.js';
2
+ import { useFormMessages } from '../messages.js';
3
3
  /**
4
4
  * Shared by the three React widget sets so their action names cannot drift.
5
5
  * The array title is read from the document rather than the node prop: these
@@ -8,14 +8,15 @@ import { addActionName, removeActionName } from '../props/action-names.js';
8
8
  */
9
9
  export function useArrayActions(node) {
10
10
  const { document } = useRendererContext();
11
+ const messages = useFormMessages();
11
12
  const current = (document.nodes[node.id] ?? node);
12
- const arrayTitle = current.annotations.title;
13
+ const containerTitle = current.annotations.title;
13
14
  return {
14
- removeName: (position, item) => removeActionName(position, item?.annotations.title, arrayTitle),
15
+ remove: (position, item) => messages.removeItem({ position, itemTitle: item?.annotations.title, containerTitle }),
15
16
  // The item template's title, not the first row's. A row may not exist yet,
16
17
  // which is exactly when naming the add control matters most, and a row's
17
18
  // annotations can in principle depend on its data.
18
- addName: addActionName(current.arrayMeta?.itemTitle, arrayTitle),
19
+ add: messages.addItem({ itemTemplateTitle: current.arrayMeta?.itemTitle, containerTitle }),
19
20
  };
20
21
  }
21
22
  //# sourceMappingURL=use-array-actions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-array-actions.js","sourceRoot":"","sources":["../../src/hooks/use-array-actions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AACtE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAS1E;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,EAAE,QAAQ,EAAE,GAAG,kBAAkB,EAAE,CAAA;IACzC,MAAM,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAkB,CAAA;IAClE,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,KAAK,CAAA;IAC5C,OAAO;QACL,UAAU,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,CAAC,KAAK,EAAE,UAAU,CAAC;QAC/F,2EAA2E;QAC3E,yEAAyE;QACzE,mDAAmD;QACnD,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC;KACjE,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"use-array-actions.js","sourceRoot":"","sources":["../../src/hooks/use-array-actions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAShD;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,EAAE,QAAQ,EAAE,GAAG,kBAAkB,EAAE,CAAA;IACzC,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAA;IAClC,MAAM,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAkB,CAAA;IAClE,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,KAAK,CAAA;IAChD,OAAO;QACL,MAAM,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,CACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,KAAK,EAAE,cAAc,EAAE,CAAC;QACvF,2EAA2E;QAC3E,yEAAyE;QACzE,mDAAmD;QACnD,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;KAC3F,CAAA;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -9,11 +9,11 @@ export { useFieldBinding } from './hooks/use-field-binding.js';
9
9
  export { useObjectGroup } from './hooks/use-object-group.js';
10
10
  export { useArrayActions } from './hooks/use-array-actions.js';
11
11
  export type { ArrayActions } from './hooks/use-array-actions.js';
12
- export { removeActionName, moveUpActionName, addActionName } from './props/action-names.js';
13
12
  export type { ObjectGroup } from './hooks/use-object-group.js';
14
13
  export type { FieldBinding, DomValueInputProps, DomCheckedInputProps, DomInputBaseProps, } from './hooks/use-field-binding.js';
15
14
  export { FormContext, FormProvider, useFormContext } from './context.js';
16
15
  export type { FormProviderProps } from './context.js';
16
+ export { useFormMessages } from './messages.js';
17
17
  export { useFormIdPrefix } from './id-prefix.js';
18
18
  export { getInputProps, getLabelProps, getErrorProps, getDescriptionProps, hasNativeReadOnly, } from './props/index.js';
19
19
  export type { InputProps, LabelProps, ErrorProps, DescriptionProps, FieldState } from './props/index.js';
@@ -21,11 +21,12 @@ export { FormRoot } from './components/FormRoot.js';
21
21
  export type { FormRootProps } from './components/FormRoot.js';
22
22
  export { NodeRenderer } from './components/NodeRenderer.js';
23
23
  export type { NodeRendererProps } from './components/NodeRenderer.js';
24
- export { FieldLabelContent, REQUIRED_INDICATOR } from './components/FieldLabelContent.js';
24
+ export { FieldLabelContent } from './components/FieldLabelContent.js';
25
25
  export type { FieldLabelContentProps } from './components/FieldLabelContent.js';
26
26
  export { FieldErrors } from './components/FieldErrors.js';
27
27
  export type { FieldErrorsProps } from './components/FieldErrors.js';
28
28
  export { ErrorSummary } from './components/ErrorSummary.js';
29
+ export type { ErrorSummaryProps } from './components/ErrorSummary.js';
29
30
  export { useRendererContext } from './components/renderer-context.js';
30
31
  export type { WidgetComponent, RendererContextValue } from './components/renderer-context.js';
31
32
  export { TextInput, NumberInput, Checkbox, Select, Textarea, ObjectLayout, ArrayControl, createDefaultRegistry, } from './widgets/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,YAAY,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAChE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAC3F,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAC9D,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AACxE,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AACxG,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AACnD,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,YAAY,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AACrE,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AACzF,YAAY,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAA;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AACzD,YAAY,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AACrE,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAA;AAC7F,OAAO,EACL,SAAS,EACT,WAAW,EACX,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,qBAAqB,GACtB,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,YAAY,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAChE,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAC9D,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AACxE,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AACxG,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AACnD,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,YAAY,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAA;AACrE,YAAY,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAA;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AACzD,YAAY,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,YAAY,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AACrE,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAA;AAC7F,OAAO,EACL,SAAS,EACT,WAAW,EACX,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,qBAAqB,GACtB,MAAM,oBAAoB,CAAA"}
package/dist/index.js CHANGED
@@ -5,13 +5,13 @@ export { useFieldArray } from './hooks/use-field-array.js';
5
5
  export { useFieldBinding } from './hooks/use-field-binding.js';
6
6
  export { useObjectGroup } from './hooks/use-object-group.js';
7
7
  export { useArrayActions } from './hooks/use-array-actions.js';
8
- export { removeActionName, moveUpActionName, addActionName } from './props/action-names.js';
9
8
  export { FormContext, FormProvider, useFormContext } from './context.js';
9
+ export { useFormMessages } from './messages.js';
10
10
  export { useFormIdPrefix } from './id-prefix.js';
11
11
  export { getInputProps, getLabelProps, getErrorProps, getDescriptionProps, hasNativeReadOnly, } from './props/index.js';
12
12
  export { FormRoot } from './components/FormRoot.js';
13
13
  export { NodeRenderer } from './components/NodeRenderer.js';
14
- export { FieldLabelContent, REQUIRED_INDICATOR } from './components/FieldLabelContent.js';
14
+ export { FieldLabelContent } from './components/FieldLabelContent.js';
15
15
  export { FieldErrors } from './components/FieldErrors.js';
16
16
  export { ErrorSummary } from './components/ErrorSummary.js';
17
17
  export { useRendererContext } from './components/renderer-context.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAE1D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAE9D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAQ3F,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAExE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAE3D,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AAEzF,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAErE,OAAO,EACL,SAAS,EACT,WAAW,EACX,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,qBAAqB,GACtB,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAE1D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAS9D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAExE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAA;AAErE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAE3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAErE,OAAO,EACL,SAAS,EACT,WAAW,EACX,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,qBAAqB,GACtB,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,5 @@
1
+ import type { FormMessages } from '@texaryn/core';
2
+ export declare const MessagesProvider: import("react").Provider<FormMessages>;
3
+ /** English when nothing is provided: unlike a missing id prefix, a missing locale has a safe answer. */
4
+ export declare function useFormMessages(): FormMessages;
5
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAIjD,eAAO,MAAM,gBAAgB,wCAA2B,CAAA;AAExD,wGAAwG;AACxG,wBAAgB,eAAe,IAAI,YAAY,CAE9C"}
@@ -0,0 +1,9 @@
1
+ import { createContext, useContext } from 'react';
2
+ import { englishMessages } from '@texaryn/core';
3
+ const MessagesContext = createContext(englishMessages);
4
+ export const MessagesProvider = MessagesContext.Provider;
5
+ /** English when nothing is provided: unlike a missing id prefix, a missing locale has a safe answer. */
6
+ export function useFormMessages() {
7
+ return useContext(MessagesContext);
8
+ }
9
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAG/C,MAAM,eAAe,GAAG,aAAa,CAAe,eAAe,CAAC,CAAA;AAEpE,MAAM,CAAC,MAAM,gBAAgB,GAAG,eAAe,CAAC,QAAQ,CAAA;AAExD,wGAAwG;AACxG,MAAM,UAAU,eAAe;IAC7B,OAAO,UAAU,CAAC,eAAe,CAAC,CAAA;AACpC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ArrayControl.d.ts","sourceRoot":"","sources":["../../src/widgets/ArrayControl.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,KAAK,EAAiB,MAAM,EAAE,MAAM,eAAe,CAAA;AAM1D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;CACb;AAED,iBAAS,gBAAgB,CAAC,EAAE,IAAI,EAAE,EAAE,WAAW,qBAqC9C;AAED,eAAO,MAAM,YAAY,oDAGxB,CAAA"}
1
+ {"version":3,"file":"ArrayControl.d.ts","sourceRoot":"","sources":["../../src/widgets/ArrayControl.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,KAAK,EAAiB,MAAM,EAAE,MAAM,eAAe,CAAA;AAM1D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;CACb;AAED,iBAAS,gBAAgB,CAAC,EAAE,IAAI,EAAE,EAAE,WAAW,qBAsC9C;AAED,eAAO,MAAM,YAAY,oDAGxB,CAAA"}
@@ -11,12 +11,13 @@ function ArrayControlImpl({ node }) {
11
11
  const actions = useArrayActions(node);
12
12
  return (_jsxs("div", { children: [fieldArray.items.map((item, index) => {
13
13
  const childNode = item.nodeId ? document.nodes[item.nodeId] : undefined;
14
+ const remove = actions.remove(index + 1, childNode);
14
15
  return (_jsxs("div", { children: [childNode ? (_jsx(NodeRenderer, { node: childNode, document: document, registry: registry })) : null, fieldArray.canRemove ? (
15
16
  // The visible word stays short; the name that distinguishes the
16
17
  // row goes in aria-label, which contains it so speech input
17
18
  // still works.
18
- _jsx("button", { type: "button", "aria-label": actions.removeName(index + 1, childNode), onClick: () => fieldArray.remove(index), children: "Remove" })) : null] }, item.id));
19
- }), fieldArray.canAdd ? (_jsx("button", { type: "button", "aria-label": actions.addName, onClick: () => fieldArray.add(), children: "Add" })) : null] }));
19
+ _jsx("button", { type: "button", "aria-label": remove.accessibleName, onClick: () => fieldArray.remove(index), children: remove.label })) : null] }, item.id));
20
+ }), fieldArray.canAdd ? (_jsx("button", { type: "button", "aria-label": actions.add.accessibleName, onClick: () => fieldArray.add(), children: actions.add.label })) : null] }));
20
21
  }
21
22
  export const ArrayControl = React.memo(ArrayControlImpl, (prev, next) => prev.node.id === next.node.id);
22
23
  //# sourceMappingURL=ArrayControl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ArrayControl.js","sourceRoot":"","sources":["../../src/widgets/ArrayControl.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAM/D,SAAS,gBAAgB,CAAC,EAAE,IAAI,EAAe;IAC7C,MAAM,aAAa,GAAG,IAAqB,CAAA;IAC3C,MAAM,UAAU,GAAG,aAAa,CAAC,aAAa,CAAC,EAAE,CAAC,CAAA;IAClD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,kBAAkB,EAAE,CAAA;IACnD,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA;IAErC,OAAO,CACL,0BACG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBACpC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;gBACvE,OAAO,CACL,0BACG,SAAS,CAAC,CAAC,CAAC,CACX,KAAC,YAAY,IAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,GAAI,CAC1E,CAAC,CAAC,CAAC,IAAI,EACP,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;wBACtB,gEAAgE;wBAChE,4DAA4D;wBAC5D,eAAe;wBACf,iBACE,IAAI,EAAC,QAAQ,gBACD,OAAO,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,EAAE,SAAS,CAAC,EACpD,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,uBAGhC,CACV,CAAC,CAAC,CAAC,IAAI,KAfA,IAAI,CAAC,EAAE,CAgBX,CACP,CAAA;YACH,CAAC,CAAC,EACD,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CACnB,iBAAQ,IAAI,EAAC,QAAQ,gBAAa,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,oBAEzE,CACV,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CACpC,gBAAgB,EAChB,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,CAC9C,CAAA"}
1
+ {"version":3,"file":"ArrayControl.js","sourceRoot":"","sources":["../../src/widgets/ArrayControl.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAM/D,SAAS,gBAAgB,CAAC,EAAE,IAAI,EAAe;IAC7C,MAAM,aAAa,GAAG,IAAqB,CAAA;IAC3C,MAAM,UAAU,GAAG,aAAa,CAAC,aAAa,CAAC,EAAE,CAAC,CAAA;IAClD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,kBAAkB,EAAE,CAAA;IACnD,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA;IAErC,OAAO,CACL,0BACG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBACpC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;gBACvE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE,SAAS,CAAC,CAAA;gBACnD,OAAO,CACL,0BACG,SAAS,CAAC,CAAC,CAAC,CACX,KAAC,YAAY,IAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,GAAI,CAC1E,CAAC,CAAC,CAAC,IAAI,EACP,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;wBACtB,gEAAgE;wBAChE,4DAA4D;wBAC5D,eAAe;wBACf,iBACE,IAAI,EAAC,QAAQ,gBACD,MAAM,CAAC,cAAc,EACjC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,YAEtC,MAAM,CAAC,KAAK,GACN,CACV,CAAC,CAAC,CAAC,IAAI,KAfA,IAAI,CAAC,EAAE,CAgBX,CACP,CAAA;YACH,CAAC,CAAC,EACD,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CACnB,iBAAQ,IAAI,EAAC,QAAQ,gBAAa,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,YAC1F,OAAO,CAAC,GAAG,CAAC,KAAK,GACX,CACV,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CACpC,gBAAgB,EAChB,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,CAC9C,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@texaryn/react",
3
- "version": "0.4.4",
3
+ "version": "0.5.1",
4
4
  "description": "React bindings, hooks, prop getters, and default widgets for Texaryn",
5
5
  "keywords": [
6
6
  "react",
@@ -24,7 +24,7 @@
24
24
  "url": "git+https://github.com/texaryn/texaryn.git",
25
25
  "directory": "packages/react"
26
26
  },
27
- "homepage": "https://github.com/texaryn/texaryn#readme",
27
+ "homepage": "https://texaryn.github.io/texaryn/",
28
28
  "bugs": {
29
29
  "url": "https://github.com/texaryn/texaryn/issues"
30
30
  },
@@ -44,7 +44,7 @@
44
44
  "CHANGELOG.md"
45
45
  ],
46
46
  "dependencies": {
47
- "@texaryn/core": "^0.11.0"
47
+ "@texaryn/core": "^0.12.1"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "react": ">=18.0.0"
@@ -56,7 +56,7 @@
56
56
  "jsdom": "^25.0.0",
57
57
  "react": "^19.0.0",
58
58
  "react-dom": "^19.0.0",
59
- "@texaryn/schema-json": "0.6.0"
59
+ "@texaryn/schema-json": "0.6.2"
60
60
  },
61
61
  "scripts": {
62
62
  "build": "tsc --build"
@@ -1,19 +0,0 @@
1
- /**
2
- * Accessible names for the controls an array renders.
3
- *
4
- * Five identical "Remove" buttons tell a screen reader user nothing about
5
- * which row they act on. The name carries the current 1-based position, which
6
- * is what a person means by "the second contact"; the stable item id is
7
- * implementation identity and means nothing to them.
8
- *
9
- * The row's own value is deliberately not used. It is mutable, often blank,
10
- * frequently duplicated, sometimes long, and sometimes sensitive.
11
- *
12
- * Titles come from the schema: the array's own title, and the item title,
13
- * which repeats across rows and so cannot distinguish them on its own. Each
14
- * name degrades cleanly as those go missing.
15
- */
16
- export declare function removeActionName(position: number, itemTitle: string | undefined, arrayTitle: string | undefined): string;
17
- export declare function moveUpActionName(position: number, itemTitle: string | undefined, arrayTitle: string | undefined): string;
18
- export declare function addActionName(itemTitle: string | undefined, arrayTitle: string | undefined): string;
19
- //# sourceMappingURL=action-names.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"action-names.d.ts","sourceRoot":"","sources":["../../src/props/action-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,MAAM,CAER;AAED,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,MAAM,CAER;AAED,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,MAAM,CAGR"}
@@ -1,30 +0,0 @@
1
- /**
2
- * Accessible names for the controls an array renders.
3
- *
4
- * Five identical "Remove" buttons tell a screen reader user nothing about
5
- * which row they act on. The name carries the current 1-based position, which
6
- * is what a person means by "the second contact"; the stable item id is
7
- * implementation identity and means nothing to them.
8
- *
9
- * The row's own value is deliberately not used. It is mutable, often blank,
10
- * frequently duplicated, sometimes long, and sometimes sensitive.
11
- *
12
- * Titles come from the schema: the array's own title, and the item title,
13
- * which repeats across rows and so cannot distinguish them on its own. Each
14
- * name degrades cleanly as those go missing.
15
- */
16
- export function removeActionName(position, itemTitle, arrayTitle) {
17
- return withContainer(`Remove ${itemTitle ?? 'item'} ${position}`, 'from', arrayTitle);
18
- }
19
- export function moveUpActionName(position, itemTitle, arrayTitle) {
20
- return withContainer(`Move up ${itemTitle ?? 'item'} ${position}`, 'in', arrayTitle);
21
- }
22
- export function addActionName(itemTitle, arrayTitle) {
23
- if (arrayTitle !== undefined)
24
- return `Add item to ${arrayTitle}`;
25
- return itemTitle === undefined ? 'Add item' : `Add ${itemTitle}`;
26
- }
27
- function withContainer(name, preposition, arrayTitle) {
28
- return arrayTitle === undefined ? name : `${name} ${preposition} ${arrayTitle}`;
29
- }
30
- //# sourceMappingURL=action-names.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"action-names.js","sourceRoot":"","sources":["../../src/props/action-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,gBAAgB,CAC9B,QAAgB,EAChB,SAA6B,EAC7B,UAA8B;IAE9B,OAAO,aAAa,CAAC,UAAU,SAAS,IAAI,MAAM,IAAI,QAAQ,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,CAAA;AACvF,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,QAAgB,EAChB,SAA6B,EAC7B,UAA8B;IAE9B,OAAO,aAAa,CAAC,WAAW,SAAS,IAAI,MAAM,IAAI,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;AACtF,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,SAA6B,EAC7B,UAA8B;IAE9B,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,eAAe,UAAU,EAAE,CAAA;IAChE,OAAO,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,SAAS,EAAE,CAAA;AAClE,CAAC;AAED,SAAS,aAAa,CAAC,IAAY,EAAE,WAAmB,EAAE,UAA8B;IACtF,OAAO,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,WAAW,IAAI,UAAU,EAAE,CAAA;AACjF,CAAC"}